<?php
namespace App\Wen\Utils;
use App\Http\Controllers\Api\NotifyController;
use App\Http\Controllers\Api\Repositories\WxContRepositories;
use App\Http\Controllers\Api\Repositories\WxNoticeRepositories;
use App\Http\Controllers\Api\Repositories\WxUserRepositores;
use App\Jobs\SubscribeMessageJob;
use App\Jobs\User\UpdateUserAnonymousInfoJob;
use App\Jobs\UserBgColorUpdateJob;
use App\Lib\Uploads\UploadHandler;
use App\Models\Pets\WxPetsAdoption;
use App\Models\Posts\WxComment;
use App\Models\Posts\WxPost;
use App\Models\Circle\WxCircle;
use App\Models\Shop\WxShop;
use App\Models\Shop\WxShopAddress;
use App\Models\Shop\WxShopGoods;
use App\Models\Shop\WxShopGoodsProduct;
use App\Models\Shop\WxShopGuaranteeRecord;
use App\Models\Shop\WxShopOrder;
use App\Models\Shop\WxShopOrderGoods;
use App\Models\User\WxUserFinancialFreeze;
use App\Models\User\WxUserSetting;
use App\Models\Voter\WxVoter;
use App\Models\Voter\WxVoterPlayer;
use App\Models\Voter\WxVoterPlayerBallot;
use App\Models\WxAuthentication;
use App\Models\WxChat;
use App\Models\WxTask;
use App\Models\User\WxUser;
use App\Models\User\WxUserAvatarFrame;
use App\Models\User\WxUserAvatarFramePurchase;
use App\Models\User\WxUserCoinRecord;
use App\Models\User\WxUserExperience;
use App\Models\User\WxUserFinancial;
use App\Models\User\WxUserFinancialRecord;
use App\Models\User\WxUserFollow;
use App\Models\User\WxUserInviteBenefitRecord;
use App\Models\User\WxUserOnline;
use App\Models\User\WxUserPlate;
use App\Models\User\WxUserSignRecord;
use App\Models\User\WxUserVisit;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Intervention\Image\Facades\Image;
use Illuminate\Http\UploadedFile;

class UserUtils{

    public static function distance($uid, $longitude, $latitude){
        $user = self::get_cached_user($uid);
        if($user){
            if($user['longitude'] && $user['latitude']){
                $lng1=$user['longitude']; //经度1

                $lat1=$user['latitude']; //纬度1

                $lng2=$longitude; //经度2

                $lat2=$latitude; //纬度2

                $EARTH_RADIUS = 6378137; //地球半径

                $RAD = pi() / 180.0;

                $radLat1 = $lat1 * $RAD;

                $radLat2 = $lat2 * $RAD;

                $a = $radLat1 - $radLat2; // 两点纬度差

                $b = ($lng1 - $lng2) * $RAD; // 两点经度差

                $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));

                $s = $s * $EARTH_RADIUS;

                $s = round($s * 10000) / 10000;

                return $s;
            }
        }
        Cache::forget('get:cached:user:'.$uid);
        return null;
    }

    public static function get_simple_cached_user($user_id, $columns){
        $user = self::get_cached_user($user_id);
        $res = [];
        if($user){
            foreach ($columns as $column){
                $res[$column] = $user[$column];
            }
        }
        return $res;
    }

    public static function get_anonymous_info(WxUser &$user, $change = 0){
        if($user){
            if($user->anonymous_name && $change != 1){
                return [
                    'anonymous_name'=>$user->anonymous_name,
                    'anonymous_avatar'=>$user->anonymous_avatar
                ];
            }else{
                $anonymous_name_avatar = Settings::get('anonymous_name_avatar', [], true);
                if(_empty_($anonymous_name_avatar) || !is_array($anonymous_name_avatar)){
                    return null;
                }
                $name_avatar = $anonymous_name_avatar[mini_rand(0, count($anonymous_name_avatar) - 1)];
                if($name_avatar && is_array($name_avatar)){
                    WxUser::withoutSyncingToSearch(function () use (&$user, &$name_avatar){
                        WxUser::where('id', $user->id)->update([
                            'anonymous_name' => $name_avatar['name'],
                            'anonymous_avatar' => $name_avatar['avatar']
                        ]);
                        Cache::forget('get:cached:user:'.$user->id);
                        UpdateUserAnonymousInfoJob::dispatch($user->id * -1);
                    });
                    return [
                        'anonymous_name' => _array_key($name_avatar, 'name', ''),
                        'anonymous_avatar' => _array_key($name_avatar, 'avatar', '')
                    ];
                }else{
                    return null;
                }
            }
        }else{
            return null;
        }
    }

    public static function get_cached_user($user_id, $online_info = false, $message_reply_rate = false, $anonymous = false){
        if(_empty_($user_id)){
            return null;
        }
        $user = Cache::remember('get:cached:user:'.$user_id, 3600, function () use ($user_id){
            try {
                $user = WxUser::where('id', $user_id)->first(FieldUtils::userInfoColums());
            }catch (\Exception $e){
                if(strpos($e->getMessage(), 'Column not found') !== false){
                    SiteUtils::forget_config_data();
                }else{
                    _logger_(__file__, __line__, $e->getMessage());
                    return null;
                }
            }
            if($user){
                self::user_expend($user);
                return $user->toArray();
            }
            return null;
        });

        if($user){

            if($anonymous){
                $user['user_name'] = $user['anonymous_name'];
                $user['user_avatar'] = $user['anonymous_avatar'];
            }

            if(_array_key($user, 'is_robot', 0) > 0){
                global $__MINI_GLOBAL_IS_ADMIN_SUPER__;
                if($__MINI_GLOBAL_IS_ADMIN_SUPER__){
                    $user['user_name'] =  $user['user_name'].' 🤖';
                }
            }

            if($online_info){
                $online_item = WxUserOnline::where('user_id', $user['id'])->first(['online', 'device']);
                if($online_item){
                    $user['online_time'] = format_datetime($online_item->online);
                    $user['device'] = $online_item->device;
                }else{
                    $user['online_time'] = '';
                    $user['device'] = '';
                }
            }

            if($message_reply_rate){
                $user['message_replay_rate'] = (self::message_response_rate($user['id']) * 100) . '%' ;
            }

            if(_empty_(_array_key($user, 'setting', null))){
                Cache::forget('get:cached:user:'.$user['id']);
                $user['setting'] = WxUserSetting::find($user['id']);
                if(_empty_($user['setting'])){
                    $user_setting = new WxUserSetting();
                    $user_setting->user_id = $user['id'];
                    $user_setting->save();
                    $user->setting = WxUserSetting::find($user['id']);
                }
            }

            if(_empty_(_array_key($user, 'user_background_color', ''))){
                Cache::forget('get:cached:user:'.$user['id']);
                UserBgColorUpdateJob::dispatch($user['id'], false);
                $user['user_background_color'] = '63,47,45';
            }
            return $user;
        }
        return null;
    }

    public static function user_expend(&$user, $left_panel = false, $publish = false, $shop = false, $used = false, $scene = 0){

        Redis::sadd('robot:timed:user:active', $user->id);

        if(_empty_($user)){
            return;
        }

        $user->paycode = get_user_meta($user->id, 'paycode', 's') ? '******' : '';
        $user->coins = UserUtils::user_coins($user->id);
        $user->lv = UserUtils::lv($user->id);
        $user->honor = get_user_meta($user->id, 'honor');
        $user->user_labels = get_user_meta($user->id, 'user_labels', 'j');
        $user->avatar_frame_url = get_user_meta($user->id, 'cur_avatar_frame');
        $user->age = StrUtils::age($user->user_birthday);
        $user->constellation = StrUtils::constellation($user->user_birthday);
        $user->setting = WxUserSetting::find($user->id);

        if($shop){
            if($user->shop_id && $user->shop_id > 0){
                $user->shop = WxShop::where('id', $user->shop_id)->where('status', 1)->first(FieldUtils::shopInfoColums());
            }else{
                $user->shop = null;
            }
        }else{
            // 占位
            $user->shop = null;
        }

        $user->user_background_color = get_user_meta($user->id, 'user_background_color');
        if(_empty_($user->user_background_color)){
            UserBgColorUpdateJob::dispatch($user->id, false);
            $user->user_background_color = '63,47,45';
        }

        if(_empty_($user->setting)){
            $user_setting = new WxUserSetting();
            $user_setting->user_id = $user->id;
            $user_setting->save();
            $user->setting = WxUserSetting::find($user->id);
        }

        if($user->is_authentication){
            if($user->authentication_id && $user->authentication_id > 0){
                $user->authentication = WxAuthentication::find($user->authentication_id);
            }else{
                $user->authentication = WxAuthentication::where([
                    ['user_id', '=', $user->id],
                    ['authentication_state', '=', 1]
                ])->orderBy('id', 'desc')->first();
            }
        }

        if($left_panel){
            global $__MINI_GLOBAL_PAYCODE_20__,$__MINI_GLOBAL_PAYCODE_16__,$__MINI_GLOBAL_PLATFORM__,$__MINI_GLOBAL_DEVICE__;
            $is_exam = is_mini_examine_mode(11);
            $left_pannel_arr = [];

            $left_set_panels = Settings::get('app_user_left_panel', ['my_wallet', 'payment_password', 'consumption_records', 'my_order','my_sales', 'my_shopping_bag', 'address', 'my_certification', 'my_members', 'my_circle', 'my_team']);
            $left_set_panels[] = 'line';
            $last_is_line = false;
            foreach (['my_wallet', 'payment_password', 'consumption_records', 'line', 'organize_bureau_center', 'organize_club_settle_in', 'line', 'my_order', 'my_sales', 'my_shopping_bag', 'address', 'line', 'my_certification', 'my_members', 'my_circle', 'my_team'] as $name){
                if(!in_array($name, $left_set_panels)){
                    continue;
                }
                if($name == 'my_wallet'){
                    if($is_exam && $__MINI_GLOBAL_PLATFORM__ == 'ios' && $__MINI_GLOBAL_DEVICE__ == 'app'){
                        continue;
                    }
                    $left_pannel_arr[] = [
                        'type' => 1,
                        'text' => '我的钱包',
                        'icon' => 'mini-wodeqianbao mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesA/mine/earnings/earnings',
                    ];
                }else if($name == 'payment_password'){
                    $left_pannel_arr[] = [
                        'type' => 1,
                        'text' => '支付密码',
                        'icon' => 'mini-zhifumima mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesA/mine/paycode/paycode?direct=0',
                    ];
                }else if($name == 'consumption_records'){
                    $left_pannel_arr[] =[
                        'type' => 1,
                        'text' => '消费记录',
                        'icon' => 'mini-xiaofeijilu mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesA/mine/order/order',
                    ];
                }else if($name == 'organize_bureau_center'){
                    $left_pannel_arr[] = [
                        'type' => 1,
                        'text' => '活动中心',
                        'icon' => 'mini-zuju mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesZ/organize-bureau/index/index',
                    ];
                }else if($name == 'organize_club_settle_in'){
                    if($user->club_id && $user->club_id > 0){
                        $left_pannel_arr[] = [
                            'type' => 1,
                            'text' => '我的俱乐部',
                            'icon' => 'mini-jiarujulebu mini-icon2',
                            'target_type' => 6,
                            'target_id' => '/pagesZ/organize-bureau/club/club?id='.$user->club_id,
                        ];
                    }else{
                        $left_pannel_arr[] = [
                            'type' => 1,
                            'text' => '俱乐部入驻',
                            'icon' => 'mini-jiarujulebu mini-icon2',
                            'target_type' => 6,
                            'target_id' => '/pagesZ/organize-bureau/settle-in/index',
                        ];
                    }

                }else if($name == 'my_order'){
                    $left_pannel_arr[] = [
                        'type' => 1,
                        'text' => '我的买入',
                        'icon' => 'mini-wodedingdan mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesA/shop/order/order',
                    ];
                }else if($name == 'my_sales'){
                    if(!$is_exam) {
                        $left_pannel_arr[] = [
                            'type' => 1,
                            'text' => '我的卖出',
                            'icon' => 'mini-womaichude mini-icon2',
                            'target_type' => 6,
                            'target_id' => '/pagesS/sellers/sales/sales',
                        ];
                        if($user->shop_id > 0){
                            $left_pannel_arr[] = [
                                'type' => 1,
                                'text' => '店铺管理',
                                'icon' => 'mini-dianpuguanli mini-icon2',
                                'target_type' => 6,
                                'target_id' => '/pagesA/shop/apply/apply',
                            ];
                        }
                    }
                }else if($name == 'my_shopping_bag'){
                    $left_pannel_arr[] = [
                        'type' => 1,
                        'text' => '我的购物袋',
                        'icon' => 'mini-wodegouwudai mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesA/shop/cart/cart',
                    ];
                }else if($name == 'address'){
                    $left_pannel_arr[] = [
                        'type' => 1,
                        'text' => '收货地址',
                        'icon' => 'mini-shouhuodizhi mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesA/mine/address/address?id=0',
                    ];
                }else if($name == 'my_certification'){
                    $left_pannel_arr[] = [
                        'type' => 1,
                        'text' => '我的认证',
                        'icon' => 'mini-woderenzheng mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesA/mine/certification/certification',
                    ];
                }else if($name == 'my_members'){
                    if(!$is_exam){
                        if($__MINI_GLOBAL_PAYCODE_16__){
                            $left_pannel_arr[] = [
                                'type' => 1,
                                'text' => '我的会员',
                                'icon' => 'mini-wodehuiyuan mini-icon2',
                                'target_type' => 6,
                                'target_id' => '/pagesA/mine/members/members',
                            ];
                        }
                    }
                }else if($name == 'my_circle'){
                    $left_pannel_arr[] = [
                        'type' => 1,
                        'text' => '我的'.env('circle_call', '圈子'),
                        'icon' => 'mini-wodequanzi mini-icon2',
                        'target_type' => 6,
                        'target_id' => '/pagesA/mine/circleaudit/circleaudit',
                    ];
                }else if($name == 'my_team'){
                    if(!$is_exam) {
                        if ($__MINI_GLOBAL_PAYCODE_20__ && Settings::get('user_invite_benefit_status', 1) == 1) {
                            if ($user->lv >= Settings::get('app_user_lv_invite_benefit', 1)) {
                                $left_pannel_arr[] = [
                                    'type' => 1,
                                    'text' => '我的团队',
                                    'icon' => 'mini-wodetuandui mini-icon2',
                                    'target_type' => 6,
                                    'target_id' => '/pagesA/mine/invite/invite',
                                ];
                            }
                        }
                    }
                }


                if($name == 'line'){
                    if(!$last_is_line){
                        $last_is_line = true;
                        $left_pannel_arr[] = [
                            'type' => 0,
                        ];
                    }
                }else{
                    $last_is_line = false;
                }

            }
            $user->leftPanel = $left_pannel_arr;
        }

        if($publish){
            $publish_arr = [];
            $publish_video_lv = Settings::get('app_user_lv_publish_video', 2);
            global $__MINI_GLOBAL_PLATFORM__,$__MINI_GLOBAL_DEVICE__;
            $is_exam = is_mini_examine_mode(11);

            $simple_fixed = Settings::get('app_publish_simple_fixed', '101,102,103,104,105,106', true);
            if($simple_fixed){
                foreach (explode(',', $simple_fixed) as $code) {
                    if($code == 102 || $code == 303){
                        if($user->lv < $publish_video_lv || $is_exam){
                            continue;
                        }
                    }
                    if($__MINI_GLOBAL_DEVICE__ == 'app' && $is_exam && $__MINI_GLOBAL_PLATFORM__ == 'ios' && ($code == 104)){
                        continue;
                    }
                    $icon = self::add_publish_icon($code, 1);
                    if($icon){
                        $publish_arr[] = $icon;
                    }

                }
            }

            $simple_popup = Settings::get('app_publish_simple_popup', '201,202,203,204', true);
            if($simple_popup){
                foreach (explode(',', $simple_popup) as $code) {
                    if($code == 102 || $code == 303){
                        if($user->lv < $publish_video_lv || $is_exam){
                            continue;
                        }
                    }
                    if($__MINI_GLOBAL_DEVICE__ == 'app' && $is_exam && $__MINI_GLOBAL_PLATFORM__ == 'ios' && ($code == 104)){
                        continue;
                    }
                    $icon = self::add_publish_icon($code, 2);
                    if($icon){
                        $publish_arr[] = $icon;
                    }

                }
            }

            $imagetext_fixed = Settings::get('app_publish_imagetext_fixed', '301,302,303,305,306,307,308', true);
            if($imagetext_fixed){
                foreach (explode(',', $imagetext_fixed) as $code) {
                    if($code == 102 || $code == 303){
                        if($user->lv < $publish_video_lv || $is_exam){
                            continue;
                        }
                    }
                    if($__MINI_GLOBAL_DEVICE__ == 'app' && $is_exam && $__MINI_GLOBAL_PLATFORM__ == 'ios' && ($code == 104)){
                        continue;
                    }
                    $icon = self::add_publish_icon($code, 3);
                    if($icon){
                        $publish_arr[] = $icon;
                    }
                }
            }

            $imagetext_popup = Settings::get('app_publish_imagetext_popup', '201,202,203,204', true);
            if($imagetext_popup){
                foreach (explode(',', $imagetext_popup) as $code) {
                    if($code == 102 || $code == 303){
                        if($user->lv < $publish_video_lv || $is_exam){
                            continue;
                        }
                    }
                    if($__MINI_GLOBAL_DEVICE__ == 'app' && $is_exam && $__MINI_GLOBAL_PLATFORM__ == 'ios' && ($code == 104)){
                        continue;
                    }
                    $icon = self::add_publish_icon($code, 4);
                    if($icon){
                        $publish_arr[] = $icon;
                    }

                }
            }
            $user->publish = $publish_arr;
        }

        if($scene == 5 || $scene == 8){
            if($scene == 5){
                $grid_display_force = Settings::get('app_user_grid_display_force', []);
            }else{
                $grid_display_force = Settings::get('app_user_grid_three_display_force', []);
            }
            if(_empty_($grid_display_force)){
                $grid_display_force = [];
            }

            $grid = [];
            $card_count = ShopUtils::user_cart_count($user->id);
            $order_count = ShopUtils::get_order_count($user->id);
            $tip = '买过的商品';
            if($order_count){
                if( _array_key($order_count, 'payCount', 0) > 0 ){
                    $tip = $order_count['payCount'].'件待付款';
                }else if( _array_key($order_count, 'deliverCount', 0) > 0 ){
                    $tip = $order_count['deliverCount'].'件待发货';
                }else if( _array_key($order_count, 'closedCount', 0) > 0 ){
                    $tip = $order_count['closedCount'].'件待晒单';
                }
            }
            if($scene == 8){
                if($user->setting && _array_key($user->setting, 'social_sph_id', '')){
                    $grid[] = [
                        'icon' => 'mini-shipinhao',
                        'title' => '视频号',
                        'desc' => '点击跳转',
                        'target_type' => 14,
                        'path' => $user->setting['social_sph_id']
                    ];
                }
            }
            foreach ($grid_display_force as $index){
                if($index == 'my_wallet'){
                    $grid[] = [
                        'icon' => 'mini-icon2 mini-wodeqianbao',
                        'title' => '我的钱包',
                        'desc' => '查看余额和'.Settings::get('app_coin_name', '硬币'),
                        'target_type' => 6,
                        'path' => '/pagesA/mine/earnings/earnings'
                    ];
                }
                else if($index =='my_organize_bureau'){
                    $grid[] = [
                        'icon' => 'mini-icon2 mini-zuju',
                        'title' => '我的组局',
                        'desc' => '看看一起玩过的',
                        'target_type' => 6,
                        'path' => '/pagesZ/organize-bureau/my-list/index'
                    ];
                }
                else if($index == 'my_vip'){
                    if(!$is_exam) {
                        $grid[] = [
                            'icon' => 'mini-icon2 mini-wodehuiyuan',
                            'title' => '我的会员',
                            'desc' => $user->is_member ? '尊享会员' : '未开通',
                            'target_type' => 6,
                            'path' => '/pagesA/mine/members/members'
                        ];
                    }
                }else if($index == 'my_shop_order'){
                    $grid[] = [
                        'icon' => 'mini-icon2 mini-wodedingdan',
                        'title' => '我的买入',
                        'desc' => $tip,
                        'target_type' => 6,
                        'path' => '/pagesA/shop/order/order'
                    ];
                }else if($index == 'my_shop_bag'){
                    $grid[] = [
                        'icon' => 'mini-icon2 mini-wodegouwudai',
                        'title' => '我的购物袋',
                        'desc' => $card_count > 0 ? $card_count.'件商品' : '空空如也',
                        'target_type' => 6,
                        'path' => '/pagesA/shop/cart/cart'
                    ];
                }else if($index == 'my_pets_adoption'){
                    if($scene == 5){
                        $grid[] = [
                            'icon' => 'mini-songyang',
                            'title' => '我的领养',
                            'desc' => '以及送养，收藏',
                            'target_type' => 6,
                            'path' => '/pagesP/pet-adoption/pet-common-list/index?type=1'
                        ];
                    }else if($scene == 8){
                        global $__MINI_GLOBAL_PAYCODE_25__;
                        if($__MINI_GLOBAL_PAYCODE_25__){
                            $desc = '一只也没有';
                            $adopt_status_0_1 = WxPetsAdoption::where('user_id', $user->id)->whereIn('adopt_status', [0, 1])->get();
                            if($adopt_status_0_1){
                                $adopt_status_0 = 0;
                                $adopt_status_1 = 0;
                                $adopt_status_0_1->map(function ($v) use (&$adopt_status_0, &$adopt_status_1){
                                    if($v->adopt_status == 1){
                                        $adopt_status_1 += 1;
                                    }else{
                                        $adopt_status_0 += 1;
                                    }
                                });
                                if($adopt_status_0 > 0){
                                    $desc = $adopt_status_0.'只待送养';
                                }else{
                                    if($adopt_status_1 > 0){
                                        $desc = '空空如也';
                                    }else{
                                        $desc = $adopt_status_1.'只已送养';
                                    }

                                }
                            }
                            $grid[] = [
                                'icon' => 'mini-songyang',
                                'title' => 'TA的送养',
                                'desc' => $desc,
                                'target_type' => 6,
                                'path' => '/pagesP/pet-adoption/pet-common-list/index?user_id='.$user->id.'&type=5'
                            ];
                        }
                    }

                }else if($index == 'my_used'){
                    $desc = '空空如也';
                    $counts = DB::table('wx_used_good')
                        ->select(
                            DB::raw('SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS pushingCount'),
                            DB::raw('SUM(CASE WHEN status = 3 THEN 1 ELSE 0 END) AS completedCount'),
                            DB::raw('COUNT(*) AS totalCount')
                        )
                        ->where('user_id', $user->id)->whereNotIn('status', [0,2,4])
                        ->first();

                    if($counts->pushingCount > 0){
                        $desc = $counts->pushingCount.'件闲置出售中';
                    }else if($counts->completedCount > 0){
                        $desc = '已卖出'.$counts->completedCount.'件闲置';
                    }else{
                        if($counts->totalCount > 0){
                            $desc = '共发布了'.$counts->totalCount.'件闲置';
                        }else{
                            $desc = '一件闲置也没有';
                        }
                    }

                    $grid[] = [
                        'icon' => 'mini-xianzhi1',
                        'title' => $scene == 5 ? '我的闲置' : 'TA的闲置',
                        'desc' => $desc,
                        'target_type' => 6,
                        'path' => '/pages/user/used/used?id=' . $user->id . '&name=' . $user->user_name
                    ];

                }else if($index == 'my_voter'){
                    $voter_path = '/pagesV/voter/list/list?uid='.$user->id;
                    $tip = Cache::remember('user:gird_voter:tip:'.$user->id, 3600, function () use (&$user){
                        $creat_count = WxVoter::where('user_id', $user->id)->where('status', 1)->count();
                        $tip = '';
                        if($creat_count > 0){
                            $tip = '创建了'.$creat_count.'个选票';
                        }else{
                            $player_count = WxVoterPlayer::where('user_id', $user->id)->count();
                            if($player_count > 0){
                                $tip = '报名了'.$player_count.'个选票';
                            }else{
                                $ballot_count = WxVoterPlayerBallot::where('user_id', $user->id)->count();
                                if($ballot_count > 0){
                                    $tip = $ballot_count.'次帮别人投票';
                                }
                            }
                        }
                        return $tip;
                    });

                    if(_empty_($tip)){
                        $tip = '一个投票也没有';
                    }else{
                        if(StrUtils::startsWith($tip, '报名了')){
                            $voter_path = '/pagesV/voter/list/list?uid='.$user->id.'&tab=1';
                        }else if(StrUtils::endsWith($tip, '帮别人投票')){
                            $voter_path = '/pagesV/voter/list/list?uid='.$user->id.'&tab=2';
                        }
                    }

                    $grid[] = [
                        'icon' => 'mini-icon2 mini-xuanpiao',
                        'title' => $scene == 5 ? '我的选票' : 'Ta的选票',
                        'desc' => $tip,
                        'target_type' => 6,
                        'path' => $voter_path
                    ];
                }
            }

            if($scene == 5){
                if($tip != '买过的商品'){
                    if(!in_array('my_shop_order', $grid_display_force)){
                        $grid[] = [
                            'icon' => 'mini-icon2 mini-wodedingdan',
                            'title' => '我的买入',
                            'desc' => $tip,
                            'target_type' => 6,
                            'path' => '/pagesA/shop/order/order'
                        ];
                    }
                }

                if($card_count > 0){
                    if(!in_array('my_shop_bag', $grid_display_force)){
                        $grid[] = [
                            'icon' => 'mini-icon2 mini-wodegouwudai',
                            'title' => '我的购物袋',
                            'desc' => $card_count > 0 ? $card_count.'件商品' : '空空如也',
                            'target_type' => 6,
                            'path' => '/pagesA/shop/cart/cart'
                        ];
                    }
                }
            }

            if($scene == 5 || $scene == 8){
                if($user->user_state === 0){
                    $user->state_tip = '正常用户';
                }else if($user->user_state === 1){
                    $user->state_tip = '该用户已注销账号';
                }else if($user->user_state === 2){
                    $ban_until = get_user_meta($user->id, 'ban_until', 's');
                    if(time() > $ban_until){
                        // 解除封号
                        if(UserUtils::unlock_user($user, 2)){
                            $user->user_state = 0;
                            $user->state_tip = '正常用户';
                        }
                    }
                    if($ban_until && $user->user_state === 2){
                        $user->state_tip = '该用户被封号至'.Carbon::createFromTimestamp($ban_until)->toDateTimeString();
                    }
                }else if($user->user_state === 3){
                    $mute_until = get_user_meta($user->id, 'mute_until', 's');
                    if(time() > $mute_until){
                        // 解除禁言
                        if(UserUtils::unlock_user($user, 3)){
                            $user->user_state = 0;
                            $user->state_tip = '正常用户';
                        }
                    }
                    if($mute_until && $user->user_state === 3){
                        $user->state_tip = '该用户被禁言至'.Carbon::createFromTimestamp($mute_until)->toDateTimeString();
                    }
                }
            }

            if($scene == 8) {
                global $__MINI_GLOBAL_PAYCODE_30__;
                if ($__MINI_GLOBAL_PAYCODE_30__) {
                    if (!in_array('my_used', $grid_display_force)) {
                        $desc = '空空如也';
                        $counts = DB::table('wx_used_good')
                            ->select(
                                DB::raw('SUM(CASE WHEN status = 1 THEN 1 ELSE 0 END) AS pushingCount'),
                                DB::raw('SUM(CASE WHEN status = 3 THEN 1 ELSE 0 END) AS completedCount'),
                                DB::raw('COUNT(*) AS totalCount')
                            )
                            ->where('user_id', $user->id)->whereNotIn('status', [0,2,4])
                            ->first();

                        if ($counts->pushingCount > 0) {
                            $desc = $counts->pushingCount . '件闲置出售中';
                        } else if ($counts->completedCount > 0) {
                            $desc = '已卖出' . $counts->completedCount . '件闲置';
                        } else {
                            if ($counts->totalCount > 0) {
                                $desc = '共发布了' . $counts->totalCount . '件闲置';
                            } else {
                                $desc = '一件闲置也没有';
                            }
                        }

                        if ($counts->totalCount > 0) {
                            $grid[] = [
                                'icon' => 'mini-xianzhi1',
                                'title' => 'TA的闲置',
                                'desc' => $desc,
                                'target_type' => 6,
                                'path' => '/pages/user/used/used?id=' . $user->id . '&name=' . $user->user_name
                            ];
                        }
                    }
                }
            }

            global $__MINI_GLOBAL_PAYCODE_33__;
            if ($__MINI_GLOBAL_PAYCODE_33__ && !in_array('my_voter', $grid_display_force)) {
                $tip = Cache::remember('user:gird_voter:tip:'.$user->id, 3600, function () use (&$user, $scene){
                    $tip_ = '';
                    if($scene == 5){
                        $creat_count = WxVoter::where('user_id', $user->id)->count();
                    }else{
                        $creat_count = WxVoter::where('user_id', $user->id)->where('status', 1)->count();
                    }

                    if($creat_count > 0){
                        $tip_ = '创建了'.$creat_count.'个选票';
                    }else{
                        $player_count = WxVoterPlayer::where('user_id', $user->id)->count();
                        if($player_count > 0){
                            $tip_ = '报名了'.$player_count.'个选票';
                        }else{
                            $ballot_count = WxVoterPlayerBallot::where('user_id', $user->id)->count();
                            if($ballot_count > 0){
                                $tip_ = $ballot_count.'次帮别人投票';
                            }
                        }
                    }
                    return $tip_;
                });

                if($tip){
                    $voter_path = '/pagesV/voter/list/list?uid='.$user->id;
                    if(StrUtils::startsWith($tip, '报名了')){
                        $voter_path = '/pagesV/voter/list/list?uid='.$user->id.'&tab=1';
                    }else if(StrUtils::endsWith($tip, '帮别人投票')){
                        $voter_path = '/pagesV/voter/list/list?uid='.$user->id.'&tab=2';
                    }
                    $grid[] = [
                        'icon' => 'mini-icon2 mini-xuanpiao',
                        'title' => $scene == 5 ? '我的选票' : 'Ta的选票',
                        'desc' => $tip,
                        'target_type' => 6,
                        'path' => $voter_path
                    ];
                }
            }

            if($scene == 8){
                global $__MINI_GLOBAL_PAYCODE_25__;
                if($__MINI_GLOBAL_PAYCODE_25__){
                    if(!in_array('my_pets_adoption', $grid_display_force)) {
                        $desc = '一只也没有';
                        $adopt_status_0_1 = WxPetsAdoption::where('user_id', $user->id)->whereIn('adopt_status', [0, 1])->get();
                        if ($adopt_status_0_1->isNotEmpty()) {
                            $adopt_status_0 = 0;
                            $adopt_status_1 = 0;
                            $adopt_status_0_1->map(function ($v) use (&$adopt_status_0, &$adopt_status_1) {
                                if ($v->adopt_status == 1) {
                                    $adopt_status_1 += 1;
                                } else {
                                    $adopt_status_0 += 1;
                                }
                            });
                            if ($adopt_status_0 > 0) {
                                $desc = $adopt_status_0 . '只待送养';
                            } else if($adopt_status_1 > 0) {
                                $desc = $adopt_status_1 . '只已送养';
                            }else{
                                $desc = '空空如也';
                            }
                            $grid[] = [
                                'icon' => 'mini-songyang',
                                'title' => 'TA的送养',
                                'desc' => $desc,
                                'target_type' => 6,
                                'path' => '/pagesP/pet-adoption/pet-common-list/index?user_id=' . $user->id . '&type=5'
                            ];
                        }
                    }
                }

            }

            $user->grid = $grid;
        }


        if($scene == 8){
            $longtaps = [];
            global $__MINI_GLOBAL_CURRENT_USER_ID__;

            if($__MINI_GLOBAL_CURRENT_USER_ID__ > 0){
                if(is_object_user_special($__MINI_GLOBAL_CURRENT_USER_ID__, $user->tenant_id, true)){
                    if($user->user_state == 3){
                        $longtaps[] = [
                            'text' => '解除禁言',
                            'emoji' => '🤐',
                            'list' => [
                                [
                                    'action' => 'unmute',
                                    'name' => '解除',
                                    'user_id' => $user->id
                                ]
                            ]
                        ];
                    }else{
                        $longtaps[] = [
                            'text' => '禁言',
                            'emoji' => '🤐',
                            'list' => [
                                [
                                    'action' => 'mute',
                                    'name' => '三天',
                                    'days' => 3,
                                    'user_id' => $user->id
                                ],
                                [
                                    'action' => 'mute',
                                    'name' => '一周',
                                    'days' => 7,
                                    'user_id' => $user->id
                                ],
                                [
                                    'action' => 'mute',
                                    'name' => '一个月',
                                    'days' => 30,
                                    'user_id' => $user->id
                                ],
                                [
                                    'action' => 'mute',
                                    'name' => '三个月',
                                    'days' => 90,
                                    'user_id' => $user->id
                                ]
                            ]
                        ];
                    }
                    if($user->user_state == 2){
                        $longtaps[] = [
                            'text' => '解除封号',
                            'emoji' => '❌',
                            'list' => [
                                [
                                    'action' => 'unban',
                                    'name' => '解除',
                                    'user_id' => $user->id
                                ],
                            ]
                        ];
                    }else{
                        $longtaps[] = [
                            'text' => '封号',
                            'emoji' => '❌',
                            'list' => [
                                [
                                    'action' => 'ban',
                                    'name' => '一周',
                                    'days' => 7,
                                    'user_id' => $user->id
                                ],
                                [
                                    'action' => 'ban',
                                    'name' => '一个月',
                                    'days' => 30,
                                    'user_id' => $user->id
                                ],
                                [
                                    'action' => 'ban',
                                    'name' => '三个月',
                                    'days' => 90,
                                    'user_id' => $user->id
                                ],
                                [
                                    'action' => 'ban',
                                    'name' => '10年',
                                    'days' => 3650,
                                    'user_id' => $user->id
                                ]
                            ]
                        ];
                    }
                    $longtaps[] = [
                        'text' => '用户管理',
                        'emoji' => '🥸',
                        'list' => [
                            [
                                'name' => 'Ta的钱包',
                                'action' => 'icon',
                                'target_type' => 6,
                                'target_id' => '/pagesA/mine/earnings/earnings?uid=' . $user->id,
                                'user_id' => $user->id,
                            ],
                            [
                                'name' => 'Ta的资料',
                                'action' => 'icon',
                                'target_type' => 6,
                                'target_id' => '/pagesA/mine/editmine/editmine?uid=' . $user->id,
                                'user_id' => $user->id,
                            ],
                            [
                                'name' => '裂变层级'.$user->invite_benefit_layer,
                                'action' => 'icon',
                                'target_type' => 6,
                                'target_id' => '/pagesA/mine/invite/layer?uid=' . $user->id,
                                'user_id' => $user->id,
                            ],
                        ]
                    ];
                }
                $longtaps[] = [
                    'text' => '其他',
                    'emoji' => '😣',
                    'list' => [
                        [
                            'name' => '举报',
                            'action' => 'report',
                            'user_id' => $user->id,
                        ]
                    ]
                ];
            }
            $user->longtaps = $longtaps;
        }

    }


    /**
     * @param $uid
     * @param false $force_update_default 是否强制掉更新默认的背景色
     * @return array|mixed|string|null
     */
    public static function user_bg_color_update($uid, $force_update_default = false){
        if(!$force_update_default){
            if(_empty_($uid)){
                return '';
            }
        }

        $color_arr = [
            [81, 76, 74],
            [63, 47, 45],
            [52, 55, 39],
            [78, 90, 97],
            [75, 71, 65],
            [89, 77, 86],
            [75, 80, 85],
            [113, 93, 94],
            [132, 84, 0],
            [18, 14, 17],
            [30, 38, 72],
            [62, 56, 95],
            [26, 39, 74],
            [74, 69, 74],
            [49, 36, 75],
            [35, 67, 86],
            [114, 112, 90]
        ];

        $is_update_site = false;
        if(!$force_update_default){
            $bg = WxUser::where('id', $uid)->value('user_background_maps');
        }else{
            $uid = 0;
            $bg = '';
        }

        if(_empty_($bg)){

            if(!$force_update_default){
                $default_background_color = get_site_meta('user_background_color', 's');
                if(!_empty_($default_background_color)){
                    if($uid > 0){
                        update_user_meta($uid, 'user_background_color', $default_background_color);
                        Cache::forget('get:cached:user:'.$uid);
                    }
                    return $default_background_color;
                }
            }

            $bg = Settings::get('user_background_maps', '');
            if(_empty_($bg)){
                if($uid > 0) {
                    update_user_meta($uid, 'user_background_color', implode(',', [63, 47, 45]));
                    Cache::forget('get:cached:user:'.$uid);
                }
                return implode(',', [63, 47, 45]);
            }
            $is_update_site = true;
        }
        try {
            if(strpos($bg, 'img.mini.chongyeapp.com') !== false){
                $bg = str_replace('img.mini.chongyeapp.com', 'img.mini.minisns.cn', $bg);
            }
            // 设置图片路径
            $imagePath = file_get_contents($bg);
            $img = Image::make($imagePath);
            $mainColor = $img->limitColors(1)->pickColor(0, 0, 'array');
            $res_color = ImageUtils::find_closed_color($color_arr, $mainColor);
            if($res_color){
                $res_color = implode(',', $res_color);
                if($uid > 0) {
                    update_user_meta($uid, 'user_background_color', $res_color);
                    Cache::forget('get:cached:user:'.$uid);
                }
                if($is_update_site){
                    update_site_meta('user_background_color', $res_color);
                }
                return $res_color;
            }
        }catch (\Exception $e){
            _logger_(__file__, __line__, $e->getMessage());
            return implode(',', [63, 47, 45]);
        }
    }

    private static function add_publish_icon($code, $pos){
        global $__MINI_GLOBAL_CURRENT_PLAYER_ID__;
            if($code == 101){
                return [
                    'id' => 101,
                    'name' => '图片',
                    'icon' => 'mini-icon mini-tupian21',
                    'pos' => $pos
                ];
            }else if($code == 102){
                return [
                    'id' => 102,
                    'name' => '视频',
                    'icon' => 'mini-icon mini-shipin2',
                    'pos' => $pos
                ];
            }else if($code == 103){
                return [
                    'id' => 103,
                    'name' => '话题',
                    'icon' => 'mini-icon mini-huati2',
                    'pos' => $pos
                ];
            }else if($code == 104){
                return [
                    'id' => 104,
                    'name' => 'gif',
                    'icon' => 'mini-icon mini-gif',
                    'pos' => $pos
                ];
            }else if($code == 105){
                return [
                    'id' => 105,
                    'name' => '表情',
                    'icon' => 'mini-icon mini-biaoqing1',
                    'pos' => $pos
                ];
            }else if($code == 106){
                return [
                    'id' => 106,
                    'name' => '更多',
                    'icon' => 'mini-icon mini-tianjia1',
                    'pos' => $pos
                ];
            }else if($code == 107){
                return [
                    'id' => 107,
                    'name' => '艾特',
                    'icon' => 'mini-icon mini-a-',
                    'pos' => $pos
                ];
            }else if($code == 108){
                return [
                    'id' => 108,
                    'name' => '电话',
                    'icon' => 'mini-icon mini-dianhua',
                    'pos' => $pos
                ];
            }else if($code == 201){
                return [
                    'id' => 201,
                    'name' => '音频',
                    'icon' => 'mini-icon mini-yinpin',
                    'pos' => $pos
                ];
            }else if($code == 202){
                return [
                    'id' => 202,
                    'name' => '投票',
                    'icon' => 'mini-icon mini-toupiao-m',
                    'pos' => $pos
                ];
            }else if($code == 203){
                return [
                    'id' => 203,
                    'name' => '商品',
                    'icon' => 'mini-icon mini-shangpin11',
                    'pos' => $pos
                ];
            }else if($code == 204){
                return [
                    'id' => 204,
                    'name' => '附件',
                    'icon' => 'mini-icon mini-fujian',
                    'pos' => $pos
                ];
            }else if($code == 205){
                return [
                    'id' => 205,
                    'name' => '链接',
                    'icon' => 'mini-icon mini-lianjie',
                    'pos' => $pos
                ];
            }else if($code == 206){
                return [
                    'id' => 206,
                    'name' => '推广',
                    'icon' => 'mini-icon mini-tuiguang',
                    'pos' => $pos
                ];
            }else if($code == 207){
                global $__MINI_GLOBAL_CURRENT_USER_ID__;
                if(UserUtils::is_mini_admin($__MINI_GLOBAL_CURRENT_USER_ID__) || $__MINI_GLOBAL_CURRENT_PLAYER_ID__ > 0 || strpos(env(_multi_key('APP_PUBLISH_POST_SPH_USER'), ''), $__MINI_GLOBAL_CURRENT_USER_ID__) !== false){
                    return [
                        'id' => 207,
                        'name' => '视频号',
                        'icon' => 'mini-icon mini-shipinhao',
                        'pos' => $pos
                    ];
                }
                return null;
            }else if($code == 208){
                return [
                    'id' => 208,
                    'name' => '闲置',
                    'icon' => 'mini-icon mini-xianzhi',
                    'pos' => $pos
                ];
            }else if($code == 209){
                return [
                    'id' => 209,
                    'name' => '组局',
                    'icon' => 'mini-icon2 mini-zuju1',
                    'pos' => $pos
                ];
            }else if($code == 301){
                return [
                    'id' => 301,
                    'name' => '段落',
                    'icon' => 'mini-icon mini-wenzi1',
                    'pos' => $pos
                ];
            }else if($code == 302){
                return [
                    'id' => 302,
                    'name' => '图片',
                    'icon' => 'mini-icon mini-tupian21',
                    'pos' => $pos
                ];
            }else if($code == 303){
                return [
                    'id' => 303,
                    'name' => '视频',
                    'icon' => 'mini-icon mini-shipin2',
                    'pos' => $pos
                ];
            }else if($code == 304){
                return [
                    'id' => 304,
                    'name' => '链接',
                    'icon' => 'mini-icon mini-lianjie',
                    'pos' => $pos
                ];
            }else if($code == 305){
                return [
                    'id' => 305,
                    'name' => '音频',
                    'icon' => 'mini-icon mini-yinpin',
                    'pos' => $pos
                ];
            }else if($code == 306){
                return [
                    'id' => 306,
                    'name' => '表格',
                    'icon' => 'mini-icon mini-a-12biaoge',
                    'pos' => $pos
                ];
            }else if($code == 307){
                return [
                    'id' => 307,
                    'name' => '撤回',
                    'icon' => 'mini-icon mini-fanhui',
                    'pos' => $pos
                ];
            }else if($code == 308){
                return [
                    'id' => 308,
                    'name' => '更多',
                    'icon' => 'mini-icon mini-tianjia1',
                    'pos' => $pos
                ];
            }
    }

    public static function is_user_blacked_to($uid, $user_id){
        if(_empty_($uid) || _empty_($user_id)){
            return false;
        }
        $user_set = get_user_meta($uid, 'user:blacked:set', 'j');
        if(in_array($user_id, $user_set)){
            return true;
        }else{
            return false;
        }
    }

    /**
     * @param $user_id
     * @param $type
     * @param $amount
     * @param $reason
     * @param $para [] 数组类型
     * @return mixed|null
     */
    public static function user_financial_freeze($user_id, $type, $amount, $reason, array $para, $shop_order_id = null, $order_goods_id = null){

        if(_empty_($user_id) || _empty_($type, true) || _empty_($amount) || $amount < 0.01 || _empty_($reason) || _empty_($para)){
            return null;
        }
        if(_empty_(_array_key($para, 'type', null)) || _empty_(_array_key($para, 'tip', null))){
            return null;
        }
        if(!in_array($type, [0, 1])){
            return null;
        }

        if($type == 0){
            // 商品
            if(_empty_($shop_order_id) || _empty_($order_goods_id)){
                return null;
            }
        }

        $model = new WxUserFinancialFreeze();
        $model->user_id = $user_id;
        $model->type = $type;
        $model->freeze_amout = $amount;
        $model->freeze_reason = $reason;
        $model->freeze_status = 0;
        $model->para = json_encode($para);

        if($shop_order_id){
            $model->shop_order_id = $shop_order_id;
        }
        if($order_goods_id){
            $model->order_goods_id = $shop_order_id;
        }

        $r = $model->save();
        if($r){
            return $model->id;
        }else{
            return null;
        }
    }


    public static function get_cached_user_name($user_id, $remove_robot_flag = false){
        if(_empty_($user_id)){
            return null;
        }
        $user = self::get_cached_user($user_id);
        if($user){
            if($remove_robot_flag){
                return str_replace([' 🤖', '🤖',' 💙🤖', ' 💗🤖', '💙🤖', '💗🤖'], '', _array_key($user, 'user_name', ''));
            }else{
                return $user['user_name'];
            }
        }
        return null;
    }

    public static function lv($user_id){
        if(_empty_($user_id)){
            return 0;
        }

        return (int)Cache::remember('user:lv:'.$user_id, 3600, function () use ($user_id){
            $experience = get_user_meta($user_id, 'experience', 'n');
            if(_empty_($experience)){
                return 1;
            }
            if($experience >= 38800){
                return 6;
            }else if($experience >= 10800){
                return 5;
            }else if($experience >= 3500){
                return 4;
            }else if($experience >= 800){
                return 3;
            }else if($experience >= 60){
                return 2;
            }
            return 1;
        });

    }

    public static function add_user_experience($user_id, $type, $num = 0){
        if(_empty_($user_id) || _empty_($type, true)){
            return false;
        }
        $experience = 0;

        $today_num = WxUserExperience::where([
            ['user_id', '=', $user_id],
            ['type', '=', $type],
            ['created_at', '>=', Carbon::today()]
        ])->sum('num');
        if(_empty_($today_num)){
            $today_num = 0;
        }
        if($type == 0){
            $experience = 1;
            if($today_num >= 60){
                return false;
            }
        }else if($type == 1){
            $experience = 10;
            if($today_num >= 30){
                return false;
            }
        }else if($type == 2){
            $experience = 3;
            if($today_num >= 30){
                return false;
            }
        }else if($type == 3){
            $experience = 1;
            if($today_num >= 30){
                return false;
            }
        }else if($type == 4){
            $experience = 2;
            if($today_num >= 16){
                return false;
            }
        }else if($type == 5){
            $experience = 1;
            if($today_num >= 30){
                return false;
            }
        }else if($type == 6){
            $experience = 4;
            if($today_num >= 12){
                return false;
            }
        }else if($type == 7){
            $experience = 2;
            if($today_num >= 10){
                return false;
            }
        }else if($type == 8){
            $experience = 3;
            if($today_num >= 15){
                return false;
            }
        }else if($type == 9){
            $experience = 10;
            if($today_num >= 10){
                return false;
            }
        }else if($type == 10){
            $experience = 3;
            if($today_num >= 15){
                return false;
            }
        }else if($type == 11){
            $experience = 2;
            if($today_num >= 10){
                return false;
            }
        }else if($type == 12){
            $experience = $num;
            if($today_num >= 10){
                return false;
            }
        }else if($type == 13){
            $experience = $num;
            if($today_num >= 100){
                return false;
            }
        }else if($type == 14){
            $experience = $num;
            if($today_num >= 100){
                return false;
            }
        }else if($type == 15){
            $experience = $num;
            if($today_num >= 100){
                return false;
            }
        }
        if($experience > 0){
            $user_exper = new WxUserExperience();
            $user_exper->user_id = $user_id;
            $user_exper->type = $type;
            $user_exper->num = $experience;
            $r = $user_exper->save();
            if($r){
                $user_experience_ = get_user_meta($user_id, 'experience', 'n');
                $new_experience = $user_experience_ + $experience;

                if($new_experience >= 38800 && $user_experience_ < 38800){
                    Cache::forget('user:lv:'.$user_id);
                    Cache::forget('get:cached:user:'.$user_id);
                    UserUtils::assistant_notice($user_id, '恭喜，您的等级提升到lv6啦！');
                    GatewayUtils::success(GatewayUtils::uid2client_id($user_id), 12);
                }else if($new_experience >= 10800 && $user_experience_ < 10800){
                    Cache::forget('user:lv:'.$user_id);
                    Cache::forget('get:cached:user:'.$user_id);
                    UserUtils::assistant_notice($user_id, '恭喜，您的等级提升到lv5啦！');
                    GatewayUtils::success(GatewayUtils::uid2client_id($user_id), 12);
                }else if($new_experience >= 3500 && $user_experience_ < 3500){
                    Cache::forget('user:lv:'.$user_id);
                    Cache::forget('get:cached:user:'.$user_id);
                    UserUtils::assistant_notice($user_id, '恭喜，您的等级提升到lv4啦！');
                    GatewayUtils::success(GatewayUtils::uid2client_id($user_id), 12);
                }else if($new_experience >= 800 && $user_experience_ < 800){
                    Cache::forget('user:lv:'.$user_id);
                    Cache::forget('get:cached:user:'.$user_id);
                    UserUtils::assistant_notice($user_id, '恭喜，您的等级提升到lv3啦！');
                    GatewayUtils::success(GatewayUtils::uid2client_id($user_id), 12);
                }else if($new_experience >= 60 && $user_experience_ < 60){
                    Cache::forget('user:lv:'.$user_id);
                    Cache::forget('get:cached:user:'.$user_id);
                    UserUtils::assistant_notice($user_id, '恭喜，您的等级提升到lv2啦！');
                    GatewayUtils::success(GatewayUtils::uid2client_id($user_id), 12);
                }
                update_user_meta($user_id, 'experience', $new_experience, 'n');
                return true;
            }
        }
        return false;
    }

    public static function assistant_notice_review($expand_type, $expand_id, $to_user_id = 0){
        $assistant_user = (int)Settings::get('app_notice_review_user', 0);
        if(_empty_($assistant_user) || $assistant_user < 0){
            return;
        }
        if($to_user_id > 0){
            $users_id = [$to_user_id];
        }else{
            $users_id = explode(',', Settings::get('app_admin_super_admin', ''));
        }
        if($users_id){
            foreach (array_unique($users_id) as $to_id){
                if($to_id && $to_id > 0){

                    $chat_content_ = '';
                    if($expand_type == 101){
                        $chat_content_ = '笔记审核推送';
                    }else if($expand_type == 102){
                        $chat_content_ = '评论审核推送';
                    }else if($expand_type == 103){
                        $chat_content_ = '组局审核推送';
                    }else if($expand_type == 104){
                        $chat_content_ = '选票审核推送';
                    }else if($expand_type == 105){
                        $chat_content_ = '选票选手审核推送';
                    }else if($expand_type == 106){
                        $chat_content_ = '闲置审核推送';
                    }else if($expand_type == 107){
                        $chat_content_ = '圈子审核推送';
                    }else if($expand_type == 108){
                        $chat_content_ = '学生认证审核推送';
                    }else if($expand_type == 109){
                        $chat_content_ = '身份认证审核推送';
                    }else if($expand_type == 110){
                        $chat_content_ = '俱乐部审核推送';
                    }

                    WxChat::where('expand_type', $expand_type)->where('expand_id', $expand_id)->forceDelete();

                    $chatModel = new WxChat();
                    $chatModel->user_id = $assistant_user;
                    $chatModel->object_id = $to_id;
                    $chatModel->chat_content = $chat_content_;
                    $chatModel->chat_image = '';
                    $chatModel->chat_audio_url = '';
                    $chatModel->chat_audio_length = 0;
                    $chatModel->is_read = 0;
                    $chatModel->chat_state = 0;
                    $chatModel->expand_type = $expand_type;
                    $chatModel->expand_id = $expand_id;
                    $chatModel->save();

                    GatewayUtils::success(GatewayUtils::uid2client_id($to_id), 5, ['chat_content'=>$chat_content_, 'chat_image'=>'',
                        'from_user'=>WxUser::where('id', $assistant_user)->first(FieldUtils::userInfoColums()) ]);
                }
            }
        }
    }

    public static function assistant_notice($to_user_id, $content){
        if(_empty_($to_user_id) || _empty_($content)){
            return;
        }
        $assistant_user = (int)Settings::get('app_notice_assistant_user', 0);
        if(_empty_($assistant_user) || $assistant_user < 0){
            return;
        }

        if($to_user_id == 'admin'){
            $users_id = explode(',', Settings::get('app_admin_super_admin', ''));
            if($users_id){
                foreach ($users_id as $to_id){
                    if($to_id && $to_id > 0){
                        WxContRepositories::add($assistant_user, $to_id, $content, '', '', 0, 0);
                        $websocket_id = GatewayUtils::uid2client_id($to_id);
                        if($websocket_id){
                            GatewayUtils::success($websocket_id, 5, ['chat_content'=>strip_tags($content), 'chat_image'=>'',
                                'from_user'=>WxUser::where('id', $assistant_user)->first(FieldUtils::userInfoColums()) ]);
                        }
                    }
                }
            }
        }else{
            WxContRepositories::add($assistant_user, $to_user_id, $content, '', '', 0, 0);
            $websocket_id = GatewayUtils::uid2client_id($to_user_id);
            if($websocket_id){
                GatewayUtils::success($websocket_id, 5, ['chat_content'=>strip_tags($content), 'chat_image'=>'',
                    'from_user'=>WxUser::where('id', $assistant_user)->first(FieldUtils::userInfoColums()) ]);
            }
        }

    }

    public static function reward_user_coin($user_id, $action){
        if(_empty_($user_id) || _empty_($action)){
            return null;
        }
        if($action == 'publish'){
            $today_times = WxUserCoinRecord::where([
                ['user_id', '=', $user_id],
                ['type', '=', 11],
                ['created_at', '>=', Carbon::today()]
            ])->count();
            $max_times = Settings::get('app_coin_publish_reward_times', 1);
            if($today_times >= $max_times){
                return '';
            }
            $reward_every = Settings::get('app_coin_publish_reward_every', 10);
            if($reward_every > 0){
                self::update_user_coins($user_id, 11, $reward_every, '发帖奖励：'.Settings::get('app_coin_name', '硬币').'+'.$reward_every);
                return Settings::get('app_coin_name', '硬币').'+'.$reward_every;
            }
            return '';
        }else if($action == 'comment'){
            $today_times = WxUserCoinRecord::where([
                ['user_id', '=', $user_id],
                ['type', '=', 12],
                ['created_at', '>=', Carbon::today()]
            ])->count();
            $max_times = Settings::get('app_coin_comment_reward_times', 3);
            if($today_times >= $max_times){
                return '';
            }
            $reward_every = Settings::get('app_coin_comment_reward_every', 5);
            if($reward_every > 0){
                self::update_user_coins($user_id, 12, $reward_every, '评论奖励：'.Settings::get('app_coin_name', '硬币').'+'.$reward_every);
                return Settings::get('app_coin_name', '硬币').'+'.$reward_every;
            }
            return '';
        }else if($action == 'used-good'){
            return '';
        }else if($action == 'used-comment'){
            return '';
        }
    }

    public static function generate_text_avatar($text, $size = 200, $backgroound_color = '#8d8f9b')
    {
        if(Cache::has('generate_text_avatar:'.$text)){
            return Cache::get('generate_text_avatar:'.$text);
        }
        // 创建一个空白图像
        $image = Image::canvas($size, $size, $backgroound_color);

        // 设置文字字体、颜色和大小
        $fontPath = public_path('storage/font/DingTalk_JinBuTi_Regular.ttf');
        $textColor = '#ffffff';
        $fontSize = $size / 2;

        // 将文字居中绘制在图像上
        $image->text($text, $size / 2, $size / 2, function ($font) use ($fontPath, $textColor, $fontSize) {
            $font->file($fontPath);
            $font->size($fontSize);
            $font->color($textColor);
            $font->align('center');
            $font->valign('middle');
        });

        // 将图像保存到指定路径
        $file_name = 'images/'.md5(uniqid()) . '.png';
        $filePath = public_path('storage/' . $file_name );
        $image->save($filePath);

        $cos_res = UploadHandler::handle(new UploadedFile(public_path('storage/'.$file_name), $file_name));
        if(_array_key($cos_res, 'url', null)){
            @unlink(public_path('storage/'.$file_name));
            Cache::put('generate_text_avatar:'.$text, $cos_res['url']);
            return $cos_res['url'];
        }

        // 返回生成的头像图像路径
        @unlink(public_path('storage/'.$file_name));

        return null;
    }



    public static function user_coins($user_id){
        return get_user_meta($user_id, 'coins', 'n') ?: 0;
    }


    public static function update_user_coins($user_id, $type, $coins, $tip){
        if(_empty_($user_id) || _empty_($coins) || _empty_($tip)){
            return false;
        }

        $has_coins = get_user_meta($user_id, 'coins', 'n');
        if(_empty_($has_coins)){
            $has_coins = 0;
        }
        if($coins < 0 && $has_coins < _abs($coins)){
            return false;
        }

        $has_coins += $coins;
        $r = update_user_meta($user_id, 'coins', $has_coins, 'n');
        if($r){
            $WxUserCoinRecord = new WxUserCoinRecord();
            $WxUserCoinRecord->user_id = $user_id;
            $WxUserCoinRecord->type = $type;
            $WxUserCoinRecord->incre = $coins;
            $WxUserCoinRecord->tip = $tip;
            $r_ = $WxUserCoinRecord->save();
            return true;
        }
        return false;
    }

    public static function is_player_admin(){
        global $__MINI_GLOBAL_CURRENT_PLAYER_ID__;
        return self::is_mini_admin($__MINI_GLOBAL_CURRENT_PLAYER_ID__);
    }

    public static function is_mini_admin($uid, $not_cheeck_super = false){
        if(!$not_cheeck_super){
            if(self::is_mini_supder_admin($uid)){
                return true;
            }
        }
        global $__MINI_GLOBAL_TENANT_ID__;
        if($__MINI_GLOBAL_TENANT_ID__ > 0){
            if(get_user_meta($uid, 'tenant_id_'.$__MINI_GLOBAL_TENANT_ID__, 'n') == 1){
                return true;
            }else{
                return false;
            }
        }else{
            if(in_array($uid, explode(',', env('APP_ADMIN_USER_ID', '')))){
                return true;
            }
        }
        return false;
    }

    public static function get_user_state($uid, $no_cache = false){
        if($no_cache){
            $user_state = WxUser::where('id', $uid)->value('user_state');
            if(!_empty_($user_state, true)){
                Cache::put('user:state:'.$uid, $user_state, 600);
                return $user_state;
            }
            return -1;
        }
        if(Cache::has('user:state:'.$uid)){
            return Cache::get('user:state:'.$uid);
        }else{
            $user_state = WxUser::where('id', $uid)->value('user_state');
            if(!_empty_($user_state, true)){
                Cache::put('user:state:'.$uid, $user_state, 600);
                return $user_state;
            }
        }
        return -1;
    }


    public static function is_user_can_upload($uid){
        $state = self::get_user_state($uid);
        if($state == 0){
            return true;
        }
        return false;
    }


    public static function is_user_can_speak($uid){
        if(_empty_($uid)){
            return false;
        }
        $state = UserUtils::get_user_state($uid, false);
        if($state == 3){
            $mute_until = get_user_meta($uid, 'mute_until', 's');
            $the_user = WxUser::find($uid);
            if(time() > $mute_until && UserUtils::unlock_user($the_user, 3)){
                return true;
            }else{
                return false;
            }
        }
        return true;
    }


    public static function is_user_active($uid){
        $state = self::get_user_state($uid, true);
        if($state == 0){
            return true;
        }
        return false;
    }

    public static function lock_user_incre(&$user, $type, $incre_seconds, $black_reason = ''){
        $ban_until = max(get_user_meta($user->id, 'ban_until', 's'), time());
        return self::lock_user($user, $type, $ban_until + $incre_seconds, $black_reason);
    }

    /**
     * @param $user
     * @param $type 3:禁言 2：封号
     * @param $timestamp
     * @param string $black_reason
     * @return bool
     */
    public static function lock_user(&$user, $type, $timestamp, $black_reason = ''){
        if($user){
            if($type == 2){
                DB::beginTransaction();
                try {
                    // todo:
                    WxUser::where('id', $user['id'])->update( [ 'user_state' => 2, 'black_reason' => $black_reason ] );
                    update_user_meta($user['id'], 'ban_until', $timestamp, 's');
                    Cache::forget('get:cached:user:'.$user['id']);
                    Cache::forget('user:state:'.$user['id']);
                    DB::commit();
                    return true;
                } catch (\Exception $e) {
                    DB::rollBack();
                    _logger_(__file__, __line__, $e->getMessage());
                    return false;
                }
            }else if($type == 3){
                DB::beginTransaction();
                try {
                    // todo:
                    WxUser::where('id', $user['id'])->update( [ 'user_state' => 3, 'black_reason' => $black_reason ] );
                    update_user_meta($user['id'], 'mute_until', $timestamp, 's');
                    Cache::forget('get:cached:user:'.$user['id']);
                    Cache::forget('user:state:'.$user['id']);
                    DB::commit();
                    return true;
                } catch (\Exception $e) {
                    DB::rollBack();
                    _logger_(__file__, __line__, $e->getMessage());
                    return false;
                }
            }
        }
        return false;
    }

    public static function unlock_user(&$user, $type){
        global $__MINI_GLOBAL_CURRENT_USER_ID__;
        if($user){
            if($type == 2){
                if($user['user_state'] === 2){
                    $ban_until = get_user_meta($user['id'], 'ban_until', 's');
                    // 解除封号
                    DB::beginTransaction();
                    try {
                        // todo:
                        WxUser::where('id', $user['id'])->update( [ 'user_state' => 0 ] );
                        update_user_meta($user['id'], 'ban_until', null, 's');
                        Cache::forget('get:cached:user:'.$user['id']);
                        DB::commit();
                        GatewayUtils::success(GatewayUtils::uid2client_id($user['id']), 12);
                        return true;
                    } catch (\Exception $e) {
                        DB::rollBack();
                        _logger_(__file__, __line__, $e->getMessage());
                        return false;
                    }
                }
            }else if($type == 3){
                if($user['user_state'] === 3){
                    $mute_until = get_user_meta($user['id'], 'mute_until', 's');
                    // 解除禁言
                    DB::beginTransaction();
                    try {
                        // todo:
                        WxUser::where('id', $user['id'])->update( [ 'user_state' => 0 ] );
                        update_user_meta($user['id'], 'mute_until', null, 's');
                        Cache::forget('get:cached:user:'.$user['id']);
                        update_user_meta($user['id'], 'sql_injection_times', 0, 'n');
                        DB::commit();
                        GatewayUtils::success(GatewayUtils::uid2client_id($user['id']), 12);
                        return true;
                    } catch (\Exception $e) {
                        DB::rollBack();
                        _logger_(__file__, __line__, $e->getMessage());
                        return false;
                    }
                }
            }
            return false;
        }else{
            return false;
        }
    }

    public static function is_user_not_active($uid){
        return !self::is_user_active($uid);
    }

    public static function is_user_can_chat($uid){
        $state = self::get_user_state($uid, true);
        if($state == 0){
            return true;
        }
        return false;
    }


    public static function user_permissions_check_by_config($uid, $key){
        if(_empty_($uid) || _empty_($key)){
            return false;
        }
        $permissions = Settings::get($key, []);
        if(self::user_permissions_check($uid, $permissions)){
            return true;
        }
        if($permissions && in_array(10, $permissions)){
            if(in_array($uid, Settings::get($key.'_users', []))){
                return true;
            }
        }
        return false;
    }

    // 满足任一权限返回true
    public static function user_permissions_check($uid, $permissions){

        if(_empty_($uid)){
            return false;
        }

        if(UserUtils::is_mini_supder_admin($uid)){
            return true;
        }

        if(_empty_($permissions) || !is_array($permissions)){
            return false;
        }

        foreach ($permissions as $permissions_code){
            if($permissions_code == 1){
                if(WxUser::where('id', $uid)->value('is_authentication') == 1){
                    return true;
                }
            }else if($permissions_code == 2){
                if(WxUser::where('id', $uid)->value('is_member')){
                    return true;
                }
            }else if($permissions_code == 3){
                if(UserUtils::is_mini_admin($uid)){
                    return true;
                }
            }else if(in_array($permissions_code, [4,5,6,7,8,9])){
                if(UserUtils::lv($uid) >= $permissions_code - 3){
                    return true;
                }
            }
        }
        return false;
    }

    public static function user_action_permissions_check($uid, $action = 'publish_post'){
        $arr = ['code'=>0, 'msg'=>''];
        if(_empty_($uid)){
            return $arr;
        }
        $state = self::get_user_state($uid, true);
        if($state != 0){
            $arr['msg'] = '用户非正常状态';
            return $arr;
        }
        $permissions_code = 0;
        if($action == 'publish_post'){
            $permissions_code = Settings::get('app_publish_permissions', 0, true);
        }else if($action == 'create_circle'){
            $permissions_code = Settings::get('app_create_circle_permissions', 0, true);
        }else if($action == 'user_authenticate'){
            $permissions_code = Settings::get('app_user_authenticate_permissions', 0);
        }

        if($permissions_code == 0 || self::is_mini_admin($uid)){
            $arr['code'] = 1;
            return $arr;
        }

        // 认证用户
        if($permissions_code == 1){
            if(WxUser::where('id', $uid)->value('is_authentication') != 1){
                $arr['msg'] = '您没有[认证用户]权限';
                GatewayUtils::warn_message(GatewayUtils::uid2client_id($uid), '仅认证用户可以发布内容');
                return $arr;
            }
        }else if($permissions_code == 2){
            if(!WxUser::where('id', $uid)->value('is_member')){
                $arr['msg'] = '您没有[会员]权限';
                GatewayUtils::warn_message(GatewayUtils::uid2client_id($uid), '仅会员可以发布内容');
                return $arr;
            }

        }else if($permissions_code == 3){
            GatewayUtils::warn_message(GatewayUtils::uid2client_id($uid), '仅管理员可以发布内容');
            $arr['msg'] = '您没有[管理员]权限';
            return $arr;
        }else if(in_array($permissions_code, [4,5,6,7,8,9])){
            if(UserUtils::lv($uid) < $permissions_code - 3){
                $arr['msg'] = '您没有[lv'.($permissions_code - 3).']权限';
                GatewayUtils::warn_message(GatewayUtils::uid2client_id($uid), '仅会员可以发布内容');
                return $arr;
            }
        }

        $arr['code'] = 1;
        return $arr;
    }

    public static function is_user_online($uid, $minutes = 5){
        if(_empty_($uid)){
            return false;
        }
        if(GatewayUtils::uid2client_id($uid)){
            return true;
        }else{
            return WxUserOnline::where('user_id', $uid)->where('online', '>=', Carbon::now()->subMinutes($minutes))->exists();
        }
    }

    public static function get_user_online_time($uid, $is_format = false){
        if(_empty_($uid)){
            return false;
        }
        $online = WxUserOnline::where('user_id', $uid)->value('online');
        if($online){
            if($is_format){
                return format_datetime($online, 1);
            }
        }
        return null;
    }

    public static function user_onlines($return_uids = 0, $sub_minute = 5, $page = 0){
        $offset = ($page - 1) * 15;
        if($return_uids == 1){
            if($page > 0){
                return WxUserOnline::where('online', '>', now()->subMinute($sub_minute))->orderBy('online', 'desc')->offset($offset)->limit(15)->pluck('user_id')->toArray();
            }else{
                return WxUserOnline::where('online', '>', now()->subMinute($sub_minute))->orderBy('online', 'desc')->pluck('user_id')->toArray();
            }
        }if($return_uids == 2){
            if($page > 0){
                return DB::table('wx_user')->select(['wx_user.id', 'wx_user.user_name','wx_user.user_avatar','wx_user_online.online'])->leftJoin('wx_user_online', 'wx_user.id', '=', 'wx_user_online.user_id')
                    ->where('wx_user_online.online', '>', now()->subMinute($sub_minute))->orderBy('wx_user_online.online', 'desc')
                    ->simplePaginate(15);
            }else{
                return  WxUserOnline::where('online', '>', now()->subMinute($sub_minute))->orderBy('online', 'desc')->get();
            }
        }else{
            return WxUserOnline::where('online', '>', now()->subMinute($sub_minute))->count();
        }
    }

    public static function is_mini_supder_admin($uid){
        if(_empty_($uid)){
            return false;
        }
        global $__MINI_GLOBAL_IS_ADMIN_SUPER__, $__MINI_GLOBAL_CURRENT_USER_ID__;
        if($uid > 0 && in_array($uid, explode(',', env('APP_SUPER_ADMIN_USER_ID', '')))){
            if($__MINI_GLOBAL_CURRENT_USER_ID__ == $uid){
                $__MINI_GLOBAL_IS_ADMIN_SUPER__ = true;
            }
            return true;
        }
        try{
            if($uid > 0 && in_array( $uid, explode(',', Settings::get('app_admin_super_admin', '')) )){
                // 主站管理员
                if($__MINI_GLOBAL_CURRENT_USER_ID__ == $uid){
                    $__MINI_GLOBAL_IS_ADMIN_SUPER__ = true;
                    _update_env([
                        'APP_SUPER_ADMIN_USER_ID' => Settings::get('app_admin_super_admin', ''),
                    ], [], 1);
                }
                return true;
            }

            global $__MINI_GLOBAL_TENANT_ID__;
            if($__MINI_GLOBAL_TENANT_ID__ > 0){
                if(in_array( $uid, explode(',', Settings::get('app_admin_super_admin', '', true)) )){
                    return true;
                }
            }
        }catch (\Exception $e){
            return false;
        }
        return false;
    }

    public static function  is_circle_admin($circle_id, $uid){
        return WxCircle::where([
            ['id', '=', $circle_id],
            ['user_id', '=', $uid]
        ])->exists();
    }

    public static function is_post_circle_admin($post_id, $uid){
        $circle_id = WxPost::where('id', $post_id)->value('circle_id');
        if($circle_id){
            return self::is_circle_admin($circle_id, $uid);
        }
        return null;
    }

    public static function field_user_privacy($user){
        // ['phone', 'user_birthday', 'user_mobile', 'weixin_name']
        $user['phone'] = md5($user['phone']);
        $user['user_birthday'] = md5($user['user_birthday']);
        $user['user_mobile'] = md5($user['user_mobile']);
        $user['weixin_name'] = md5($user['weixin_name']);
        return $user;
    }

    public static function set_online($user_id, $device = '', $device_model = '', $system = ''){
        if(_empty_($user_id)){
            return false;
        }

        $updates = ['online'=>current_time()];
        if($device){
            $updates['device'] = $device;
        }

        if($device_model){
            $updates['device_model'] = $device_model;
        }

        if($system){
            $updates['system'] = $system;
        }
        $r = WxUserOnline::updateOrCreate(['user_id' => $user_id], $updates);

        if($r){
            return true;
        }
        return false;
    }

    public static function user_balance($uid){
        return WxUserFinancial::where('user_id', $uid)->value('balance') ?? 0;
    }

    public static function follow_user($uid, $user_follow_id){
        // 不能关注自己
        $res = ['code'=>0, 'message'=>''];
        if($user_follow_id == $uid){
            $res['message'] = 403023;
            return $res;
        }

        $isExists = WxUserFollow::where('user_follow_id', $user_follow_id)
            ->where('user_id', $uid)
            ->exists();
        if (!$isExists) {
            // 关注
            $wxLike = new WxUserFollow();
            $wxLike->user_follow_id = $user_follow_id;
            $wxLike->user_id = $uid;
            $wxLike->save();
            Redis::sadd('realtime:others:set', json_encode([$user_follow_id, 4, 1]));
            UserUtils::add_user_experience($uid, 8);

            $res['code'] = 1;
            $res['message'] = 403021;

        } else {
            // 取消关注
            (new WxUserFollow())->where('user_follow_id', $user_follow_id)
                ->where('user_id', $uid)
                ->delete();
            $res['code'] = 1;
            $res['message'] = 403022;
        }
        Cache::forget('user:fans:count:'.$user_follow_id);
        Cache::forget('user:follow:count:'.$uid);
        Cache::forget($uid.':follow:user:'.$user_follow_id);
        return $res;
    }

    /**
     * @param $user_id
     * @param $type getUserFinancialType
     * @param $nums
     * @param $tip 给用户发送的通知
     * @param int $postsId
     * @param string $bank_name
     * @param string $bank_card
     * @return bool
     */
    public static function update_user_financial($user_id, $type, $nums, $tip, $postsId = 0, $bank_name = '', $bank_card = ''){
        // 「 」
        if(_empty_($user_id) || _empty_($nums) || _empty_($tip)){
            return false;
        }
        if($nums < 0){
            _logger_(__file__, __line__, '出现了修改余额，nums参数为负数的情况');
            return false;
        }
        // 充电
        if($type == 0){
            if(_empty_($postsId)){
                return false;
            }
        }

        if(in_array($type, [0, 1, 3, 4, 5, 6, 12,15, 16, 17, 18, 20, 23, 24, 25, 26, 28, 29, 31, 33, 10002])){
            // 增加余额
            $financial = WxUserFinancial::where('user_id', $user_id)->exists();
            if ($financial) {
                $uf = WxUserFinancial::where('user_id', $user_id)->first();
                $balance = $uf['balance'] + $nums;
                $sumPrice = $uf['sum_price'] + $nums;
                WxUserFinancial::where('user_id', $user_id)
                    ->update(['balance' => $balance, 'sum_price' => $sumPrice,]);
            } else {
                $userFinancialModel = new WxUserFinancial();
                $userFinancialModel->user_id = $user_id;
                $userFinancialModel->balance = $nums;
                $userFinancialModel->sum_price = $nums;
                $userFinancialModel->save();
            }
        }

        // 提现
        if($type == 2){
            $wd = WxUserFinancial::where('user_id', $user_id)->first();
            if(_empty_($wd)){
                return false;
            }

            if($wd['balance'] - $nums < 0){
                return false;
            }
            $balance = $wd['balance'] - $nums;
            $withdrawalPrice = ($wd['withdrawal_price'] ?? 0) + $nums;
            WxUserFinancial::where('user_id', $user_id)
                ->update(['bank_name' => $bank_name, 'bank_card' => $bank_card, 'balance' => $balance, 'withdrawal_price' => $withdrawalPrice]);
        }

        if(in_array($type, [7, 8, 9, 10, 11, 13, 19, 21, 22, 27, 30, 32, 10001])){
            // 购买付费
            $wd = WxUserFinancial::where('user_id', $user_id)->first();
            if(_empty_($wd)){
                return false;
            }

            if($wd['balance'] - $nums < 0){
                return false;
            }
            $balance = $wd['balance'] - $nums;
            WxUserFinancial::where('user_id', $user_id)->update(['balance'=>$balance]);
        }


        $record = new WxUserFinancialRecord();
        $record->user_id = $user_id;
        if(in_array($type, [2, 7, 8, 9, 10, 11, 13, 19, 21, 22, 27, 30, 32, 10001])){
            $record->num = -$nums;
        }else{
            $record->num = $nums;
        }
        $record->type = $type;
        $record->object = $postsId;
        $record->tip = $tip;
        $record->save();

        // 通知用户
        UserUtils::add_user_notice(7005, $user_id, '余额变动提醒：'.FieldUtils::getUserFinancialType()[(int)$type], $tip, 100, $postsId);

        return true;
    }

    public static function get_user_shop_address($uid){
        if(_empty_($uid)){
            return null;
        }
        return WxShopAddress::where('user_id', $uid)->orderBy('is_check', 'desc')->first();
    }

    public static function user_gift($uid, $financialType, $type, $num, $tip, $coin_record = 8, $product_id = 0){
        if($type == 0){
            self::update_user_coins($uid, $coin_record, $num, $tip);
            return Settings::get('app_coin_name', '硬币').'*'.$num;
        }else if($type == 1){
            self::update_user_financial($uid, $financialType, $num, $tip);
            return '余额*'.$num;
        }else if($type == 2){
            WxUserRepositores::vip($uid, $num);
            return 'Vip*'.$num.'天';
        }else if($type == 3){
            $product_id = trim(trim($product_id, ','));
            if(_empty_($product_id)){
                return $product_id.'规格id不存在';
            }
            if($product_id > 0){
                $product = WxShopGoodsProduct::where('id', $product_id)->first();
                if($product){
                    if($product->stock <= 0){
                        return '商品规格'.$product_id.'库存不足';
                    }
                    DB::beginTransaction();
                    try {
                        $NotifyController = new NotifyController();
                        $orderSn = Utils::getSn(1);//生成订单号
                        $is_vip = false;
                        $goods_amount = $product->price * $num;
                        $addsinfo = self::get_user_shop_address($uid);
                        if(_empty_($addsinfo)){
                            $addsinfo = [
                                'name' => '未填写',
                                'mobile' => '16600000000',
                                'province' => '北京市',
                                'city' => '北京市',
                                'county' => '东城区',
                                'adds' => '长安街'
                            ];
                            UserUtils::add_user_notice(6002, $uid, '订单缺陷', '您抽奖获取的奖品订单缺少收货地址，请您及时更新，点击进入<a href="/pagesA/shop/order/order">我的买入</a>', 100);
                        }
                        $WxShopGoods = WxShopGoods::where('id', $product->goods_id)->first();
                        // todo:
                        //生成SHOP订单
                        $order_model = new WxShopOrder();
                        $order_model->user_id = $uid;
                        $order_model->seller_user_id = $WxShopGoods->user_id;
                        $order_model->order_id = $orderSn;//订单号
                        $order_model->goods_amount = $goods_amount;//商品总价
                        $order_model->discounts_amount = 0;//优惠金额
                        $order_model->order_amount = 0;//实付
                        $order_model->adds_id =  _array_key($addsinfo, 'id', null);//收货地址id
                        $order_model->adds_name = $addsinfo['name'];//收货人姓名
                        $order_model->adds_mobile = $addsinfo['mobile'];//收货人电话
                        $order_model->address = $addsinfo['province'] . $addsinfo['city'] . $addsinfo['county'] . $addsinfo['adds'];//收货详细地址
                        $order_model->user_remark = '抽奖获得';//用户备注
                        $order_model->pay_status = 1;//支付状态 1=未付款 2=已付款 3=已退款
                        $order_model->status = 0;//发货状态 0=正常 1=未发货 2=已发货 3=确认收货 4=已退货 5=取消
                        $order_model->order_goods_id = [$WxShopGoods->id];
                        if($WxShopGoods->contact_id){
                            $order_model->contact_id = $WxShopGoods->contact_id;
                        }

                        $order_model->save();



                        $orderId = $order_model->id;//获取订单id

                        //
                        $_goods_amount = 0;
                        $_order_amount = 0;

                        //批量添加订单商品
                        $orderGoods = [];
                        $good_servers = $WxShopGoods->service_id;
                        if(_empty_($good_servers)){
                            $good_servers = '[]';
                        }
                        $created_at = date('Y-m-d H:i:s', time());
                        $good_servers = json_decode($good_servers, true);
                        $refund_deadline = Carbon::now()->addDays(7);
                        if(in_array(1, $good_servers)){
                            $refund_deadline = Carbon::now();
                            $created_at = $refund_deadline;
                        }
                        $recharge = $is_vip ? $product->vip_price * $num : $product->price * $num;
                        $_order_amount += $recharge;
                        $_goods_amount += $product->price * $num;

                        $orderGoods[0]['pic'] = $product->pic;
                        $orderGoods[0]['name'] = $WxShopGoods->name;
                        $orderGoods[0]['product'] = $product->param_value;
                        $orderGoods[0]['vip_price'] = $product->vip_price;
                        $orderGoods[0]['price'] = $product->price;
                        $orderGoods[0]['recharge'] = 0;
                        $orderGoods[0]['quantity'] = $num;
                        $orderGoods[0]['order_id'] = $orderId;
                        $orderGoods[0]['seller_user_id'] = $order_model->seller_user_id ?: 0;
                        $orderGoods[0]['buyer_user_id'] = $uid;
                        $orderGoods[0]['goods_id'] = $product->goods_id;
                        $orderGoods[0]['goods_type'] = $WxShopGoods->type;
                        $orderGoods[0]['product_id'] = $product->id;
                        $orderGoods[0]['created_at'] = $created_at;
                        $orderGoods[0]['refund_deadline'] = $refund_deadline;

                        $ogModel = new WxShopOrderGoods();
                        $ogModel->addAll($orderGoods);

                        WxShopOrder::where('id', $orderId)
                            ->update(['pay_status' => 2, 'status' => 1, 'coins_num'=>0, 'coins_pay'=>0, 'pay_way'=>ShopUtils::generate_payway_text(0,0, 0,0,0, 0, 0, 0, true)]);
                        WxShopGoodsProduct::where('id', $product_id)->update(['stock' => $product->stock - 1]);//减库存

                        // 理论上闲置商品不可以当做礼物
                        $NotifyController->usedGoodPaied($orderId);
                        $NotifyController->bureauGoodPaied($orderId);

                        ShopUtils::paied_content_process($orderId);
                        ShopUtils::split_shop_order_by_seller($orderId);
                        ShopUtils::split_shop_order_by_type($orderId);
                        ShopUtils::order_buys_and_stock($orderId);

                        DB::commit();
                        return $WxShopGoods->goods_name.'[规格：'.$product->param_value.']*'.$num;
                    } catch (\Exception $e) {
                        DB::rollBack();
                        _logger_(__file__, __line__, $e->getMessage());
                        return '出现未知错误，请联系管理员查明';
                    }
                }
            }
        }
    }

    /**
     * @param $uid
     * @param string $date 'Y-m-d H:i:s'格式
     * @return false
     */
    public static function is_signed($uid,string $date = ''){
        if(_empty_($uid)){
            return false;
        }
        if(_empty_($date)){
            $date = current_time('day');
        }else{
            $date = date('Y-m-d', strtotime($date));
        }
        $count = WxUserSignRecord::where([['user_id', '=', $uid],['created_at', 'like', '%' . $date . '%']])->count();
        return $count > 0;
    }

    /**
     * @param $uid
     * @param string $date
     * @return bool
     */
    public static function sign_reward($uid,string $date){
        if(_empty_($uid)){
            return false;
        }
        if(_empty_($date)){
            $date = current_time();
        }
        $week = date('w', strtotime($date));
        if($week == 0){
            $week = 6;
        }else{
            $week -= 1;
        }
        $app_user_sign = Settings::get('app_user_sign', []);
        if(isset($app_user_sign[$week])){
            $reward = $app_user_sign[$week];
            UserUtils::user_gift($uid, 4, $reward['type'], $reward['num'],
                '签到奖励：'.FieldUtils::getGiftTypes()[(int)$reward['type']].'*'.$reward['num'], 7);
            return true;
        }else{
            return false;
        }
    }

    public static function task_reward($uid, $task_id){
        if(_empty_($uid) || _empty_($task_id)){
            return false;
        }
        $task = WxTask::find($task_id);
        if(_empty_($task)){
            return false;
        }
        return self::user_gift($uid, 5, $task->reward_type, $task->reward_num, '任务奖励：'.$task->name.' '.FieldUtils::getGiftTypes()[(int)$task->reward_type].'*'.$task->reward_num);
    }

    public static function add_user_notice($notice_code, $uid, $title, $content, $type, $posts_id = '', $order_id = '', $url = ''){
        if($uid > 0){
            $r = WxNoticeRepositories::addNotice($notice_code, $uid,$title,$content,$type,$posts_id, $order_id, $url);
            if($r){
                if(strpos(env('TEMPLATE_MESSAGE_NOTICE_BLACK_LIST', ''), (string)($notice_code)) === false){
                    Utils::templateMessage($uid, FieldUtils::getNoticeTypes()[(int)$type], $content, $title, '', '点击可查看详情');
                }
                if(!UserUtils::is_user_online($uid)){
                    Utils::app_push($title, $content, 999, ['target_type'=>6, 'target_id'=>'/pages/tabbar/notice/notice'], 'single', [$uid], 0);
                }else{
                    GatewayUtils::info_message(GatewayUtils::uid2client_id($uid), $title);
                }
            }
            return $r;
        }
        return 0;
    }

    public static function get_a_random_robot_uid($robot_flag = [1,2]){
        $user_id = WxUser::whereIn('is_robot', $robot_flag)->inRandomOrder()->value('id');
        if($user_id){
            return $user_id;
        }
        throw new \Exception('没有可用机器人');
    }

    public static function insert_null_user($user_name, $avatar, $sex = 0, $tenant_id = 0){
        $user_name = trim(_empty_default_($user_name, ''));
        if(_empty_($user_name) || _empty_($avatar)){
            return 0;
        }
        if (WxUser::where('user_name',$user_name)->exists()){
            return 0;
        }
//        $maxId = WxUser::max('id');
        $user = new WxUser();
        $user->weixin_openid=null;
        $user->weixin_app_openid=null;
        $user->weixin_mp_openid=null;
        $user->weixin_web_openid=null;
        $user->weixin_shop_openid=null;
        $user->weixin_unionid = null;
        $user->user_name=$user_name;
        $user->weixin_name=$user_name;
        $user->user_background_maps = Settings::get('user_background_maps');
        $user->user_avatar=$avatar ?? Settings::get('img_default');
        $user->country='';
        $user->province='';
        $user->city='';
        $user->is_robot = 1;
        // [0 => '未知',1 => '男',2 => '女']
        $user->gender=$sex;
        $user->tenant_id = $tenant_id;
        $r = $user->save();
        if($r){
//            UserUtils::set_online($user->id, ['app', 'mp'][(int)mini_rand(0,1)]);
            return $user->id;
        }
        return 0;
    }

    public static function give_coins($user_id, $coins, $post_id, $comment_id, $reply_user_id){
        $res_arr = [
            'code' => 0,
            'msg' => ''
        ];
        if(_empty_($user_id) || _empty_($post_id) || _empty_($coins)){
            return $res_arr;
        }
        $my_coins = self::user_coins($user_id);
        if($my_coins < $coins){
            $res_arr = [
                'code' => 200011,
                'msg' => '金币不足'
            ];
            return $res_arr;
        }

        $give_options = Settings::get('app_coin_give_options', []);
        if(_empty_($give_options)){
            $res_arr = [
                'code' => 200004,
                'msg' => '管理员没有配置投币'
            ];
            return $res_arr;
        }
        $flag = false;
        $exp = 0;
        foreach ($give_options as $option){
            if($option['num'] == $coins){
                $flag = true;
                $exp = $option['exp'];
                break;
            }
        }
        if(!$flag){
            $res_arr = [
                'code' => 200004,
                'msg' => '管理员没有配置'.$coins.'的投币选项'
            ];
            return $res_arr;
        }

        $platform_percent = _between_(Settings::get('app_givecoin_platform_percent', 20), 0, 100);
        if(_empty_($platform_percent)){
            $platform_percent = 0;
        }

        DB::beginTransaction();
        try{
            $user_name = self::get_cached_user_name($user_id);
            $author_id = WxPost::where('id', $post_id)->value('user_id');
            if(!_empty_($reply_user_id)){
                if($user_id == $reply_user_id){
                    DB::rollBack();
                    $res_arr = [
                        'code' => 200004,
                        'msg' => '不能给自己投币'
                    ];
                    return $res_arr;
                }
            }else{
                if($comment_id > 0){
                    $comment_author_id = WxComment::where('id', $comment_id)->value('user_id');
                    if($user_id == $comment_author_id){
                        DB::rollBack();
                        $res_arr = [
                            'code' => 200004,
                            'msg' => '不能给自己投币'
                        ];
                        return $res_arr;
                    }
                }else{
                    $comment_author_id = 0;
                    if($user_id == $author_id){
                        DB::rollBack();
                        $res_arr = [
                            'code' => 200004,
                            'msg' => '不能给自己投币'
                        ];
                        return $res_arr;
                    }
                }
            }
            if($reply_user_id > 0){
                $r = self::update_user_coins($user_id, 18, -$coins, '投币用户（id：'.$reply_user_id.'）：'.Settings::get('app_coin_name', '硬币').'-'.$coins);
            } else if($comment_author_id > 0){
                $r = self::update_user_coins($user_id, 18, -$coins, '投币评论（id：'.$comment_id.'）：'.Settings::get('app_coin_name', '硬币').'-'.$coins);
            }else{
                $r = self::update_user_coins($user_id, 18, -$coins, '投币笔记（id：'.$post_id.'）：'.Settings::get('app_coin_name', '硬币').'-'.$coins);
            }


            if($r){
                self::add_user_experience($user_id, 12, $exp);
                $rest_coins = $coins - (int)($coins * $platform_percent / 100);
                if($platform_percent > 0 && $rest_coins >= 1){
                    if($reply_user_id > 0){
                        self::update_user_coins($reply_user_id, 19, $rest_coins, $user_name.'(id: '.$user_id.') 给您投币（系统分成'.$platform_percent.'%）：'.Settings::get('app_coin_name', '硬币').'+'.$rest_coins);
                    }else if($comment_author_id > 0){
                        self::update_user_coins($comment_author_id, 19, $rest_coins, $user_name.'(id: '.$user_id.') 给您的评论（id：'.$comment_id.'）投币（系统分成'.$platform_percent.'%）：'.Settings::get('app_coin_name', '硬币').'+'.$rest_coins);
                    }else{
                        self::update_user_coins($author_id, 19, $rest_coins, $user_name.'(id: '.$user_id.') 给您的笔记（id：'.$post_id.'）投币（系统分成'.$platform_percent.'%）：'.Settings::get('app_coin_name', '硬币').'+'.$rest_coins);
                    }
                }else{
                    if($reply_user_id > 0){
                        self::update_user_coins($reply_user_id, 19, $coins, $user_name.'(id: '.$user_id.') 给您投币：'.Settings::get('app_coin_name', '硬币').'+'.$coins);
                    }else if($comment_author_id > 0){
                        self::update_user_coins($comment_author_id, 19, $coins, $user_name.'(id: '.$user_id.') 给您的评论（id：'.$comment_id.'）投币：'.Settings::get('app_coin_name', '硬币').'+'.$coins);
                    }else{
                        self::update_user_coins($author_id, 19, $coins, $user_name.'(id: '.$user_id.') 给您的笔记（id：'.$post_id.'）投币：'.Settings::get('app_coin_name', '硬币').'+'.$coins);
                    }
                }

                DB::commit();
                $res_arr = [
                    'code' => 200,
                    'msg' => '投币成功，获得经验+'.$exp,
                    'to_user' => $reply_user_id > 0 ? $reply_user_id : ($comment_author_id > 0 ? $comment_author_id : $author_id)
                ];
                return $res_arr;
            }else{
                DB::rollBack();
                $res_arr = [
                    'code' => 0,
                    'msg' => '未知'
                ];
                return $res_arr;
            }
        }catch (\Exception $e){
            DB::rollBack();
            _logger_(__file__, __line__, $e->getMessage());
            return $res_arr;
        }

    }

    public static function user_grafting($user_id, $object_id){
        if(_empty_($user_id) || _empty_($object_id)){
            return false;
        }
        if(!WxUser::where('id', $user_id)->exists() || !WxUser::where('id', $object_id)->exists()){
            return false;
        }
        // WxUser::where('weixin_openid', '')->update(['weixin_openid'=>null]);
        //        WxUser::where('weixin_unionid', '')->update(['weixin_unionid'=>null]);
        //        WxUser::where('weixin_app_openid', '')->update(['weixin_app_openid'=>null]);
        //        WxUser::where('weixin_mp_openid', '')->update(['weixin_mp_openid'=>null]);
        //        WxUser::where('weixin_web_openid', '')->update(['weixin_web_openid'=>null]);
        //        WxUser::where('weixin_shop_openid', '')->update(['weixin_shop_openid'=>null]);


//        WxPost::where('user_id', $user_id)->update(['user_id'=>$object_id]);
//        WxComment::where('user_id', $user_id)->update(['user_id'=>$object_id]);
//        WxComment::where('comment_agent_id', $user_id)->update(['comment_agent_id'=>$object_id]);
//        WxUserFollow::where('user_id', $user_id)->update(['user_id'=>$object_id]);
//        WxUserFollow::where('user_follow_id', $user_id)->update(['user_follow_id'=>$object_id]);
    }

    public static function add_user_plate($uid, $plateId){
        if(_empty_($uid) || _empty_($plateId)){
            return false;
        }
        if (WxUserPlate::where('user_id', $uid)->where('plate_id', $plateId)->exists()) {
            WxUserPlate::where('user_id', $uid)->where('plate_id', $plateId)->update(['status'=>1]);
            return true;
        }
//        $sort = $request->input('sort',100);
        $sort = WxUserPlate::where('user_id', $uid)->where('plate_id', $plateId)->orderBy('sort', 'desc')->value('sort');
        // 排序
        if (_empty_($sort)) {
            $sort = 0;
        } else {
            $sort += $sort;
        }
        $UserPlate = new WxUserPlate();
        $UserPlate->plate_id = $plateId;
        $UserPlate->user_id = $uid;
        $UserPlate->sort = $sort;
        $UserPlate->save();
        UserUtils::add_user_experience($uid, 11);
        return true;
    }

    public static function is_user_readed_circle($uid, $circle_id){
        if(_empty_($uid) || _empty_($circle_id)){
            return true;
        }
        $updated_at = WxUserVisit::where([
            ['user_id', '=', $uid],
            ['type', '=', 2],
            ['object_id', '=', $circle_id]
        ])->value('updated_at');
        if($updated_at){
            $created_at = WxPost::where([
                ['circle_id', '=', $circle_id],
                ['is_examine', '=', 1],
                ['posts_state', '=', 0],
                ['created_at', '>', $updated_at]
            ])->orderBy('created_at', 'desc')->value('created_at');
            if($created_at){
                return false;
            }else{
                return true;
            }
        }else{
            $created_at = WxPost::where([
                ['circle_id', '=', $circle_id],
                ['is_examine', '=', 1],
                ['posts_state', '=', 0],
            ])->orderBy('created_at', 'desc')->value('created_at');
            if($created_at){
                return false;
            }else{
                return true;
            }
        }
    }

    public static function get_user_invite_benifit($user_id){

        if(_empty_($user_id)){
            return null;
        }
        $res = [
            'invitelv' => '',
            'total' => 0,
            'today' => 0,
            'lv1_total' => 0,
            'lv2_total' => 0,
            'lv3_total' => 0,
            'financial' => null
        ];

        $lv1_benifit = WxUserInviteBenefitRecord::where('lv1_user', $user_id)->sum('lv1_benefit');
        $lv2_benifit = WxUserInviteBenefitRecord::where('lv2_user', $user_id)->sum('lv2_benefit');
        $lv3_benifit = WxUserInviteBenefitRecord::where('lv3_user', $user_id)->sum('lv3_benefit');

        $res['total'] = round($lv1_benifit + $lv2_benifit + $lv3_benifit, 2);
        $res['lv1_total'] = $lv1_benifit;
        $res['lv2_total'] = $lv2_benifit;
        $res['lv3_total'] = $lv3_benifit;

        if($res['total'] > 0){
            $res['invitelv'] = '一级代理人';
        }

        $today_lv1_benifit = WxUserInviteBenefitRecord::where([
            ['lv1_user','=', $user_id],
            ['created_at', '>=', Carbon::today()]
        ])->sum('lv1_benefit');
        $today_lv2_benifit = WxUserInviteBenefitRecord::where([
            ['lv2_user','=', $user_id],
            ['created_at', '>=', Carbon::today()]
        ])->sum('lv2_benefit');
        $today_lv3_benifit = WxUserInviteBenefitRecord::where([
            ['lv3_user','=', $user_id],
            ['created_at', '>=', Carbon::today()]
        ])->sum('lv3_benefit');
        $res['today'] = $today_lv1_benifit + $today_lv2_benifit + $today_lv3_benifit;

        $financial = WxUserFinancial::where('user_id', $user_id)->first();
        if($financial){
            $res['financial'] = $financial;
        }else{
            $res['financial'] = [
                'balance' => 0,
                'sum_price' => 0,
                'withdrawal_price' => 0
            ];
        }

        return $res;
    }

    public static function purchase_avatar_frame($user_id, $avatar_frame_id){
        $res = [
            'code' => 0,
            'msg' => ''
        ];
        if(_empty_($user_id) || _empty_($avatar_frame_id)){
            $res['code'] = 200001;
            $res['code'] = 200001;
            return $res;
        }

        $avatar_frame = WxUserAvatarFrame::find($avatar_frame_id);
        if(_empty_($avatar_frame)){
            $res['code'] = 200003;
            $res['tip'] = '没有'.$avatar_frame_id.'对应的头像框';
            return $res;
        }

        DB::beginTransaction();

        try{
            $record = WxUserAvatarFramePurchase::where([
                ['user_id', '=', $user_id], ['avatar_frame_id', '=', $avatar_frame->id]
            ])->first();

            if($record){
                update_user_meta($user_id, 'cur_avatar_frame', $avatar_frame->image_url, 's');
                update_user_meta($user_id, 'cur_avatar_frame_id', $avatar_frame->id, 'n');
                Cache::forget('get:cached:user:'.$user_id);
                DB::commit();
                return [
                    'code' => 200,
                    'msg' => '已经购买过'
                ];
            }else {
                $type = $avatar_frame->type;

                $flag = false;
                $tip = '';

                $credit_type = 0;
                $price = 0;
                $activity_id = 0;
                $purchase_way = 0;

                // [0=>'普通', 1=>'会员', 2=>'金币', 3=>'余额']
                if ($type == 0) {
                    $flag = true;
                    $tip = '该头像框为普通类型，直接佩戴';
                    $purchase_way = 0;
                    $res['code'] = 200;
                    $res['msg'] = '该头像框为普通类型，直接佩戴';
                }else if($type == 1){
                    $is_member = WxUser::where('id', $user_id)->value('is_member');
                    if($is_member){
                        $flag = true;
                        $tip = '会员权限解锁';
                        $purchase_way = 1;
                        $res['code'] = 200;
                        $res['msg'] = '会员权限解锁';
                    }else{
                        DB::rollBack();
                        $res['code'] = 200000;
                        $res['msg'] = '该头像框为会员专属';
                        return $res;
                    }
                }else if($type == 2){
                    $price = (int)($avatar_frame->price);
                    $coins = self::user_coins($user_id);
                    if($coins < $price){
                        DB::rollBack();
                        $res['code'] = 200011;
                        $res['msg'] = '金币不足';
                        return $res;
                    }
                    $r = self::update_user_coins($user_id, 16, -$price, '购买了头像框（id：'.$avatar_frame->id.'），金币-'.$price);
                    if($r){
                        $flag = true;
                        $purchase_way = 2;
                        $res['code'] = 200;
                        $res['msg'] = '金币购买成功';
                        $tip = '金币购买成功';
                    }else{
                        DB::rollBack();
                        $res['code'] = 200002;
                        $res['msg'] = '数据库错误';
                        return $res;
                    }
                }else{
                    DB::rollBack();
                    $res['code'] = 200004;
                    $res['msg'] = '该接口不支持购买余额类型的头像框';
                    return $res;
                }


                if($flag){
                    $model = new WxUserAvatarFramePurchase();
                    $model->user_id = $user_id;
                    $model->avatar_frame_id = $avatar_frame->id;
                    //0:普通解锁 1：会员解锁 2：金币解锁 3：余额解锁 4：活动解锁
                    $model->purchase_way = $purchase_way;
                    $model->credit_type = $credit_type;
                    $model->price = $price;
                    $model->activity_id = $activity_id;
                    $model->description = $tip;
                    $model->save();
                    update_user_meta($user_id, 'cur_avatar_frame', $avatar_frame->image_url, 's');
                    update_user_meta($user_id, 'cur_avatar_frame_id', $avatar_frame->id, 'n');
                    Cache::forget('get:cached:user:'.$user_id);
                }
            }
            DB::commit();
            return $res;
        }catch (\Exception $e){
            DB::rollBack();
            _logger_(__file__, __line__, $e->getMessage());
            $res['code'] = 200006;
            return $res;
        }

    }

    public static function get_user_member_time($uid, $timestamp = false){
        $end_time = _get_origin_attribute('wx_user', [['id', '=', $uid]], 'is_member');
        if($end_time){
            $end_time = (int)$end_time;
            if($end_time <= time()){
                $end_time = 0;
            }
        }else{
            $end_time = 0;
        }
        if($timestamp){
            return $end_time;
        }else{
            return $end_time > 0 ? timetostr($end_time) : '';
        }
    }


    public static function message_response_rate( $uid ){
        // 统计给定人收到的私信消息数（给我发私信的人数）
        $recive_message_users = WxChat::where('object_id', $uid)->distinct('user_id')->pluck('user_id');
        if($recive_message_users){
            $recive_message_users_count = count($recive_message_users);
            if($recive_message_users_count > 0){
                $replay_count = WxChat::where('user_id', $uid)->whereIn('object_id', $recive_message_users)->distinct('object_id')->count('object_id');
                return round($replay_count/$recive_message_users_count, 2);
            }
        }
        return 0;
    }

    public static function update_user_shop_gurantee($uid, $num, $title){
        if(_empty_($uid) || _empty_($title) || _empty_($num)){
            return false;
        }
        DB::beginTransaction();
        try {
            // todo:
            $shop = WxShop::where('user_id', $uid)->first();
            $margin_rest = $shop->margin_rest;
            WxShop::where('user_id', $uid)->update(['margin_rest'=> $margin_rest + $num]);
            $model = new WxShopGuaranteeRecord();
            $model->shop_id = $shop->id;
            $model->title = $title;
            $model->num = $num;
            $r = $model->save();
            UserUtils::add_user_notice(6005, $shop->user_id, '店铺保证金变动：'.$title, '保证金'.$num, 100, '', '');
            if($r){
                DB::commit();
                return true;
            }else{
                DB::rollBack();
                return false;
            }
        } catch (\Exception $e) {
            DB::rollBack();
            _logger_(__file__, __line__, $e->getMessage());
            return false;
        }

    }

    public static function authenticate_pass(WxAuthentication &$authentication, $flag = 1, $overrule_content = ''){
        $is_need_notice = false;
        if($authentication->authentication_state === 0){
            $is_need_notice = true;
        }
        if($flag == 1){
            WxAuthentication::where('id',$authentication->id)->update([
                'authentication_state'=>1
            ]);
            WxUser::where('id',$authentication->user_id)->update([
                'is_authentication'=>1,
                'authentication_id' => $authentication->id
            ]);
            if($is_need_notice){
                UserUtils::add_user_notice(4005, $authentication->user_id, '认证处理结果', '认证成功，您提交的认证已经审核通过', 100);
                SubscribeMessageJob::dispatch('authentication', $authentication->id);
            }
        }else if($flag == 2){
            WxAuthentication::where('id',$authentication->id)->update([
                'authentication_state'=>2,
                'overrule_content'=>$overrule_content
            ]);

            UserUtils::add_user_notice(4005, $authentication->user_id, '认证处理结果', '认证失败'.($overrule_content ? ','.$overrule_content : ''), 100);
            SubscribeMessageJob::dispatch('authentication', $authentication->id);
        }
        Cache::forget('total:todo:count');
        Cache::forget('total:tenant:todo:count');
    }

    /**
     * user_followed_circle_unread_post_count
     * @param $userId
     * @return int
     */
    public static function user_circle_unread_count($userId){
        if(_empty_($userId)){
            return 0;
        }
        return (int)(Cache::remember('user_circle_unread_count:'.$userId, 600, function () use (&$userId){
            // 提前获取用户最近一次访问每个圈子的时间
            $userVisits = DB::table('wx_user_visit')
                ->select('object_id', 'updated_at')
                ->where('user_id', $userId)
                ->where('type', 2)
                ->get()
                ->keyBy('object_id');

// 获取符合条件的圈子ID
            $circleIds = DB::table('wx_user_circle as uc')
                ->join('wx_circle as c', 'uc.circle_id', '=', 'c.id')
                ->where('uc.user_id', $userId)
                ->where('uc.user_circle_state', 0)
                ->where('c.circle_state', 1)
                ->pluck('uc.circle_id');

// 如果没有符合条件的圈子，直接返回0
            if ($circleIds->isEmpty()) {
                return 0;
            } else {
                // 计算符合条件的未读帖子总数
                $totalUnreadPosts = DB::table('wx_posts as p')
                    ->whereIn('p.circle_id', $circleIds)
                    ->where('p.posts_state', 0)
                    ->where('p.is_examine', 1)
                    ->where(function ($query) use (&$userVisits, &$circleIds) {
                        foreach ($userVisits as $circleId => $visit) {
                            $query->orWhere(function ($q) use ($circleId, $visit) {
                                $q->where('p.circle_id', $circleId)
                                    ->where('p.created_at', '>', $visit->updated_at);
                            });
                        }
                        $query->orWhere(function ($q) use ($userVisits, $circleIds) {
                            $q->whereIn('p.circle_id', $circleIds->diff($userVisits->keys()));
                        });
                    })
                    ->count();

                return $totalUnreadPosts;
            }
        }));
    }

}
